@elisym/sdk 0.2.0 → 0.3.0

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm](https://img.shields.io/npm/v/@elisym/sdk)](https://www.npmjs.com/package/@elisym/sdk)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../../LICENSE)
5
5
 
6
- Core TypeScript SDK for the elisym agent network. Agents discover each other, exchange jobs, send messages, and handle payments over Nostr. Payments use native SOL on Solana.
6
+ Core TypeScript SDK for the elisym agent network. Agents discover each other, exchange jobs, and handle payments over Nostr. Payments use native SOL on Solana.
7
7
 
8
8
  ## Install
9
9
 
@@ -60,9 +60,34 @@ client.close();
60
60
  | ----------------------- | ----------------------------------------------------------- |
61
61
  | `DiscoveryService` | NIP-89 agent discovery and capability publishing |
62
62
  | `MarketplaceService` | NIP-90 job lifecycle - submit, subscribe, deliver |
63
- | `MessagingService` | NIP-17 encrypted DMs + ephemeral ping/pong |
63
+ | `PingService` | Ephemeral ping/pong (kinds 20200/20201) |
64
+ | `MediaService` | NIP-96 media uploads for job attachments |
64
65
  | `SolanaPaymentStrategy` | Solana fee calculation, payment request creation/validation |
65
66
 
67
+ ## How It Works
68
+
69
+ ```
70
+ Customer Agent Provider Agent
71
+ | |
72
+ |-- discover by capability ---->| (NIP-89)
73
+ |-- submit job request -------->| (NIP-90)
74
+ |<-- payment-required ----------| (NIP-90)
75
+ |-- SOL transfer -------------->| (Solana)
76
+ |<-- job result ----------------| (NIP-90)
77
+ ```
78
+
79
+ Protocol fee: 3% (300 bps). All communication over Nostr relays, payments settle on Solana.
80
+
81
+ ## Migration: 0.2.x -> 0.3.x
82
+
83
+ NIP-17 direct messaging was removed from the SDK. For agent-to-agent communication, use targeted NIP-90 jobs (`submitJobRequest` with `providerPubkey` set) - the input and result are encrypted end-to-end with NIP-44 v2.
84
+
85
+ - `client.messaging` -> `client.ping` (only ephemeral presence remains; DM transport is gone)
86
+ - Removed exports: `MessagingService`, `KIND_GIFT_WRAP`, `LIMITS.MAX_MESSAGE_LENGTH`
87
+ - Removed methods: `sendMessage`, `fetchMessageHistory`, `subscribeToMessages`
88
+
89
+ The matching `@elisym/mcp` 0.2.x release also drops the `send_message` and `receive_messages` MCP tools.
90
+
66
91
  ## Commands
67
92
 
68
93
  ```bash
@@ -73,13 +98,6 @@ bun run test # vitest
73
98
  bun run qa # test + typecheck + lint + format check
74
99
  ```
75
100
 
76
- ## Key Patterns
77
-
78
- - **NIP-90 kind offsets**: Job request = 5000 + offset, result = 6000 + offset. Default offset: 100
79
- - **Percentage math**: Always basis points (bps), never floats. Uses `decimal.js-light`
80
- - **Peer dependencies**: `nostr-tools`, `@solana/web3.js`, `decimal.js-light` are not bundled
81
- - **Dual format**: tsup outputs both ESM (`.js`) and CJS (`.cjs`) with type declarations
82
-
83
101
  ## License
84
102
 
85
103
  MIT
package/dist/index.cjs CHANGED
@@ -4,8 +4,6 @@ var web3_js = require('@solana/web3.js');
4
4
  var Decimal2 = require('decimal.js-light');
5
5
  var nostrTools = require('nostr-tools');
6
6
  var nip44 = require('nostr-tools/nip44');
7
- var nip17 = require('nostr-tools/nip17');
8
- var nip59 = require('nostr-tools/nip59');
9
7
 
10
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
9
 
@@ -29,8 +27,6 @@ function _interopNamespace(e) {
29
27
 
30
28
  var Decimal2__default = /*#__PURE__*/_interopDefault(Decimal2);
31
29
  var nip44__namespace = /*#__PURE__*/_interopNamespace(nip44);
32
- var nip17__namespace = /*#__PURE__*/_interopNamespace(nip17);
33
- var nip59__namespace = /*#__PURE__*/_interopNamespace(nip59);
34
30
 
35
31
  // src/constants.ts
36
32
  var RELAYS = [
@@ -45,7 +41,6 @@ var KIND_JOB_REQUEST_BASE = 5e3;
45
41
  var KIND_JOB_RESULT_BASE = 6e3;
46
42
  var KIND_JOB_FEEDBACK = 7e3;
47
43
  var DEFAULT_KIND_OFFSET = 100;
48
- var KIND_GIFT_WRAP = 1059;
49
44
  var KIND_JOB_REQUEST = KIND_JOB_REQUEST_BASE + DEFAULT_KIND_OFFSET;
50
45
  var KIND_JOB_RESULT = KIND_JOB_RESULT_BASE + DEFAULT_KIND_OFFSET;
51
46
  function jobRequestKind(offset) {
@@ -89,7 +84,6 @@ var LIMITS = {
89
84
  MAX_CAPABILITIES: 20,
90
85
  MAX_DESCRIPTION_LENGTH: 500,
91
86
  MAX_AGENT_NAME_LENGTH: 64,
92
- MAX_MESSAGE_LENGTH: 1e4,
93
87
  MAX_CAPABILITY_LENGTH: 64
94
88
  };
95
89
  function assertLamports(value, field) {
@@ -1556,38 +1550,6 @@ var MediaService = class {
1556
1550
  }
1557
1551
  }
1558
1552
  };
1559
-
1560
- // src/primitives/bounded-set.ts
1561
- var BoundedSet = class {
1562
- constructor(maxSize) {
1563
- this.maxSize = maxSize;
1564
- if (maxSize <= 0) {
1565
- throw new Error("BoundedSet maxSize must be positive.");
1566
- }
1567
- this.items = new Array(maxSize);
1568
- }
1569
- items;
1570
- set = /* @__PURE__ */ new Set();
1571
- head = 0;
1572
- count = 0;
1573
- has(item) {
1574
- return this.set.has(item);
1575
- }
1576
- add(item) {
1577
- if (this.set.has(item)) {
1578
- return;
1579
- }
1580
- if (this.count >= this.maxSize) {
1581
- const evicted = this.items[this.head];
1582
- this.set.delete(evicted);
1583
- } else {
1584
- this.count++;
1585
- }
1586
- this.items[this.head] = item;
1587
- this.head = (this.head + 1) % this.maxSize;
1588
- this.set.add(item);
1589
- }
1590
- };
1591
1553
  var ElisymIdentity = class _ElisymIdentity {
1592
1554
  _secretKey;
1593
1555
  publicKey;
@@ -1628,8 +1590,8 @@ var ElisymIdentity = class _ElisymIdentity {
1628
1590
  }
1629
1591
  };
1630
1592
 
1631
- // src/services/messaging.ts
1632
- var MessagingService = class _MessagingService {
1593
+ // src/services/ping.ts
1594
+ var PingService = class _PingService {
1633
1595
  // dedup in-flight pings
1634
1596
  constructor(pool) {
1635
1597
  this.pool = pool;
@@ -1654,7 +1616,7 @@ var MessagingService = class _MessagingService {
1654
1616
  }
1655
1617
  this.pingCache.delete(agentPubkey);
1656
1618
  }
1657
- if (this.pingCache.size > _MessagingService.PING_CACHE_MAX / 2) {
1619
+ if (this.pingCache.size > _PingService.PING_CACHE_MAX / 2) {
1658
1620
  const now = Date.now();
1659
1621
  for (const [key, ts] of this.pingCache) {
1660
1622
  if (now - ts >= DEFAULTS.PING_CACHE_TTL_MS) {
@@ -1666,7 +1628,7 @@ var MessagingService = class _MessagingService {
1666
1628
  if (pending) {
1667
1629
  return pending;
1668
1630
  }
1669
- if (this.pendingPings.size >= _MessagingService.PING_CACHE_MAX) {
1631
+ if (this.pendingPings.size >= _PingService.PING_CACHE_MAX) {
1670
1632
  return { online: false, identity: null };
1671
1633
  }
1672
1634
  const promise = this._doPingWithRetry(agentPubkey, timeoutMs, retries, signal);
@@ -1715,7 +1677,7 @@ var MessagingService = class _MessagingService {
1715
1677
  if (online) {
1716
1678
  this.pingCache.delete(agentPubkey);
1717
1679
  this.pingCache.set(agentPubkey, Date.now());
1718
- if (this.pingCache.size > _MessagingService.PING_CACHE_MAX) {
1680
+ if (this.pingCache.size > _PingService.PING_CACHE_MAX) {
1719
1681
  const oldest = this.pingCache.keys().next().value;
1720
1682
  if (oldest !== void 0) {
1721
1683
  this.pingCache.delete(oldest);
@@ -1799,75 +1761,41 @@ var MessagingService = class _MessagingService {
1799
1761
  );
1800
1762
  await this.pool.publishAll(pongEvent);
1801
1763
  }
1802
- /** Send a NIP-17 DM. */
1803
- async sendMessage(identity, recipientPubkey, content) {
1804
- if (!/^[0-9a-f]{64}$/.test(recipientPubkey)) {
1805
- throw new Error("Invalid recipient pubkey: expected 64 hex characters.");
1806
- }
1807
- if (content.length > LIMITS.MAX_MESSAGE_LENGTH) {
1808
- throw new Error(
1809
- `Message too long: ${content.length} chars (max ${LIMITS.MAX_MESSAGE_LENGTH}).`
1810
- );
1764
+ };
1765
+
1766
+ // src/primitives/bounded-set.ts
1767
+ var BoundedSet = class {
1768
+ constructor(maxSize) {
1769
+ this.maxSize = maxSize;
1770
+ if (maxSize <= 0) {
1771
+ throw new Error("BoundedSet maxSize must be positive.");
1811
1772
  }
1812
- const wrap = nip17__namespace.wrapEvent(identity.secretKey, { publicKey: recipientPubkey }, content);
1813
- await this.pool.publish(wrap);
1773
+ this.items = new Array(maxSize);
1814
1774
  }
1815
- /** Fetch historical NIP-17 DMs from relays. Returns decrypted messages sorted by time. */
1816
- async fetchMessageHistory(identity, since) {
1817
- const events = await this.pool.querySync({
1818
- kinds: [KIND_GIFT_WRAP],
1819
- "#p": [identity.publicKey],
1820
- since
1821
- });
1822
- const seen = new BoundedSet(1e4);
1823
- const messages = [];
1824
- for (const ev of events) {
1825
- try {
1826
- const rumor = nip59__namespace.unwrapEvent(ev, identity.secretKey);
1827
- if (rumor.kind !== 14) {
1828
- continue;
1829
- }
1830
- if (seen.has(rumor.id)) {
1831
- continue;
1832
- }
1833
- seen.add(rumor.id);
1834
- messages.push({
1835
- senderPubkey: rumor.pubkey,
1836
- content: rumor.content,
1837
- createdAt: rumor.created_at,
1838
- rumorId: rumor.id
1839
- });
1840
- } catch {
1841
- }
1842
- }
1843
- return messages.sort((a, b) => a.createdAt - b.createdAt);
1775
+ items;
1776
+ set = /* @__PURE__ */ new Set();
1777
+ head = 0;
1778
+ count = 0;
1779
+ has(item) {
1780
+ return this.set.has(item);
1844
1781
  }
1845
- /** Subscribe to incoming NIP-17 DMs. */
1846
- subscribeToMessages(identity, onMessage, since) {
1847
- const seen = new BoundedSet(1e4);
1848
- const filter = {
1849
- kinds: [KIND_GIFT_WRAP],
1850
- "#p": [identity.publicKey]
1851
- };
1852
- if (since !== void 0) {
1853
- filter.since = since;
1782
+ add(item) {
1783
+ if (this.set.has(item)) {
1784
+ return;
1854
1785
  }
1855
- return this.pool.subscribe(filter, (ev) => {
1856
- try {
1857
- const rumor = nip59__namespace.unwrapEvent(ev, identity.secretKey);
1858
- if (rumor.kind !== 14) {
1859
- return;
1860
- }
1861
- if (seen.has(rumor.id)) {
1862
- return;
1863
- }
1864
- seen.add(rumor.id);
1865
- onMessage(rumor.pubkey, rumor.content, rumor.created_at, rumor.id);
1866
- } catch {
1867
- }
1868
- });
1786
+ if (this.count >= this.maxSize) {
1787
+ const evicted = this.items[this.head];
1788
+ this.set.delete(evicted);
1789
+ } else {
1790
+ this.count++;
1791
+ }
1792
+ this.items[this.head] = item;
1793
+ this.head = (this.head + 1) % this.maxSize;
1794
+ this.set.add(item);
1869
1795
  }
1870
1796
  };
1797
+
1798
+ // src/transport/pool.ts
1871
1799
  var NostrPool = class {
1872
1800
  pool;
1873
1801
  relays;
@@ -2114,14 +2042,14 @@ var ElisymClient = class {
2114
2042
  pool;
2115
2043
  discovery;
2116
2044
  marketplace;
2117
- messaging;
2045
+ ping;
2118
2046
  media;
2119
2047
  payment;
2120
2048
  constructor(config = {}) {
2121
2049
  this.pool = new NostrPool(config.relays ?? RELAYS);
2122
2050
  this.discovery = new DiscoveryService(this.pool);
2123
2051
  this.marketplace = new MarketplaceService(this.pool);
2124
- this.messaging = new MessagingService(this.pool);
2052
+ this.ping = new PingService(this.pool);
2125
2053
  this.media = new MediaService(config.uploadUrl);
2126
2054
  this.payment = config.payment ?? new SolanaPaymentStrategy();
2127
2055
  }
@@ -2195,7 +2123,6 @@ exports.DiscoveryService = DiscoveryService;
2195
2123
  exports.ElisymClient = ElisymClient;
2196
2124
  exports.ElisymIdentity = ElisymIdentity;
2197
2125
  exports.KIND_APP_HANDLER = KIND_APP_HANDLER;
2198
- exports.KIND_GIFT_WRAP = KIND_GIFT_WRAP;
2199
2126
  exports.KIND_JOB_FEEDBACK = KIND_JOB_FEEDBACK;
2200
2127
  exports.KIND_JOB_REQUEST = KIND_JOB_REQUEST;
2201
2128
  exports.KIND_JOB_REQUEST_BASE = KIND_JOB_REQUEST_BASE;
@@ -2207,10 +2134,10 @@ exports.LAMPORTS_PER_SOL = LAMPORTS_PER_SOL;
2207
2134
  exports.LIMITS = LIMITS;
2208
2135
  exports.MarketplaceService = MarketplaceService;
2209
2136
  exports.MediaService = MediaService;
2210
- exports.MessagingService = MessagingService;
2211
2137
  exports.NostrPool = NostrPool;
2212
2138
  exports.PROTOCOL_FEE_BPS = PROTOCOL_FEE_BPS;
2213
2139
  exports.PROTOCOL_TREASURY = PROTOCOL_TREASURY;
2140
+ exports.PingService = PingService;
2214
2141
  exports.RELAYS = RELAYS;
2215
2142
  exports.SolanaPaymentStrategy = SolanaPaymentStrategy;
2216
2143
  exports.assertExpiry = assertExpiry;