@evomap/evolver 1.69.15 → 1.69.19

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.
@@ -1,8 +1,70 @@
1
1
  // ATP (Agent Transaction Protocol) Hub Client
2
2
  // Wraps /a2a/atp/* endpoints for evolver-based agents.
3
- // Uses the same _hubPost/_hubGet pattern as a2aProtocol.js.
3
+ //
4
+ // Routing rules (#460 Bug 2):
5
+ // - When EVOMAP_PROXY=1 (or A2A_TRANSPORT=mailbox) AND a local proxy is
6
+ // running (settings.json contains proxy.url), all ATP requests are
7
+ // forwarded to the proxy's /atp/* passthrough routes so the proxy is the
8
+ // single egress point (matches mailbox/task/session behavior).
9
+ // - Otherwise, requests go directly to the Hub via the legacy _hubPost /
10
+ // _hubGet path, preserving the 1.69.x and earlier behavior for users who
11
+ // never started the proxy.
12
+ //
13
+ // The proxy overrides sender_id with its own node_id, so callers must be on
14
+ // the same node as the running proxy. This is enforced server-side (proxy is
15
+ // bound to 127.0.0.1).
4
16
 
17
+ const http = require('http');
5
18
  const { getHubUrl, buildHubHeaders, getNodeId } = require('../gep/a2aProtocol');
19
+ const { getProxyUrl } = require('../proxy/server/settings');
20
+
21
+ function _isProxyMode() {
22
+ if (process.env.EVOMAP_PROXY === '1') return true;
23
+ if (process.env.A2A_TRANSPORT === 'mailbox') return true;
24
+ return false;
25
+ }
26
+
27
+ function _proxyRequest(method, path, body, timeoutMs) {
28
+ const proxyUrl = getProxyUrl();
29
+ if (!proxyUrl) return Promise.resolve({ ok: false, error: 'proxy_not_running' });
30
+
31
+ const url = new URL(path, proxyUrl);
32
+ const timeout = timeoutMs || require('../config').HTTP_TRANSPORT_TIMEOUT_MS;
33
+
34
+ return new Promise(function (resolve) {
35
+ const payload = body ? JSON.stringify(body) : '';
36
+ const headers = { 'Content-Type': 'application/json' };
37
+ if (payload) headers['Content-Length'] = Buffer.byteLength(payload);
38
+
39
+ const req = http.request(
40
+ {
41
+ hostname: url.hostname,
42
+ port: url.port,
43
+ path: url.pathname + (url.search || ''),
44
+ method: method,
45
+ headers: headers,
46
+ timeout: timeout,
47
+ },
48
+ function (res) {
49
+ const chunks = [];
50
+ res.on('data', function (c) { chunks.push(c); });
51
+ res.on('end', function () {
52
+ const raw = Buffer.concat(chunks).toString();
53
+ if (res.statusCode >= 200 && res.statusCode < 300) {
54
+ try { resolve({ ok: true, data: JSON.parse(raw) }); }
55
+ catch (_) { resolve({ ok: true, data: { raw: raw } }); }
56
+ } else {
57
+ resolve({ ok: false, status: res.statusCode, error: raw.slice(0, 400) });
58
+ }
59
+ });
60
+ }
61
+ );
62
+ req.on('error', function (err) { resolve({ ok: false, error: err.message }); });
63
+ req.on('timeout', function () { req.destroy(); resolve({ ok: false, error: 'proxy_timeout' }); });
64
+ if (payload) req.write(payload);
65
+ req.end();
66
+ });
67
+ }
6
68
 
7
69
  function _hubPost(pathSuffix, body, timeoutMs) {
8
70
  const hubUrl = getHubUrl();
@@ -39,6 +101,23 @@ function _hubGet(pathSuffix, timeoutMs) {
39
101
  .catch(function (err) { return { ok: false, error: err.message }; });
40
102
  }
41
103
 
104
+ // Dispatcher: choose proxy or direct hub based on env + proxy availability.
105
+ // proxyPath is the path relative to proxy root (e.g. '/atp/order').
106
+ // hubPath is the path relative to hub root (e.g. '/a2a/atp/order').
107
+ function _post(proxyPath, hubPath, body, timeoutMs) {
108
+ if (_isProxyMode() && getProxyUrl()) {
109
+ return _proxyRequest('POST', proxyPath, body, timeoutMs);
110
+ }
111
+ return _hubPost(hubPath, body, timeoutMs);
112
+ }
113
+
114
+ function _get(proxyPath, hubPath, timeoutMs) {
115
+ if (_isProxyMode() && getProxyUrl()) {
116
+ return _proxyRequest('GET', proxyPath, null, timeoutMs);
117
+ }
118
+ return _hubGet(hubPath, timeoutMs);
119
+ }
120
+
42
121
  /**
43
122
  * POST /a2a/atp/order -- place an ATP order with routing
44
123
  * @param {object} opts
@@ -52,7 +131,7 @@ function _hubGet(pathSuffix, timeoutMs) {
52
131
  */
53
132
  function placeOrder(opts) {
54
133
  const nodeId = getNodeId();
55
- return _hubPost('/a2a/atp/order', {
134
+ return _post('/atp/order', '/a2a/atp/order', {
56
135
  sender_id: nodeId,
57
136
  capabilities: opts.capabilities,
58
137
  budget: Math.max(1, Math.round(Number(opts.budget) || 10)),
@@ -71,7 +150,7 @@ function placeOrder(opts) {
71
150
  */
72
151
  function submitDelivery(orderId, proofPayload) {
73
152
  const nodeId = getNodeId();
74
- return _hubPost('/a2a/atp/deliver', {
153
+ return _post('/atp/deliver', '/a2a/atp/deliver', {
75
154
  sender_id: nodeId,
76
155
  order_id: orderId,
77
156
  proof_payload: proofPayload || {},
@@ -85,7 +164,7 @@ function submitDelivery(orderId, proofPayload) {
85
164
  */
86
165
  function verifyDelivery(orderId, action) {
87
166
  const nodeId = getNodeId();
88
- return _hubPost('/a2a/atp/verify', {
167
+ return _post('/atp/verify', '/a2a/atp/verify', {
89
168
  sender_id: nodeId,
90
169
  order_id: orderId,
91
170
  action: action || 'confirm',
@@ -98,7 +177,7 @@ function verifyDelivery(orderId, action) {
98
177
  */
99
178
  function settleOrder(orderId) {
100
179
  const nodeId = getNodeId();
101
- return _hubPost('/a2a/atp/settle', {
180
+ return _post('/atp/settle', '/a2a/atp/settle', {
102
181
  sender_id: nodeId,
103
182
  order_id: orderId,
104
183
  });
@@ -111,7 +190,7 @@ function settleOrder(orderId) {
111
190
  */
112
191
  function disputeOrder(orderId, reason) {
113
192
  const nodeId = getNodeId();
114
- return _hubPost('/a2a/atp/dispute', {
193
+ return _post('/atp/dispute', '/a2a/atp/dispute', {
115
194
  sender_id: nodeId,
116
195
  order_id: orderId,
117
196
  reason: reason,
@@ -124,7 +203,8 @@ function disputeOrder(orderId, reason) {
124
203
  */
125
204
  function getMerchantTier(nodeId) {
126
205
  const nid = nodeId || getNodeId();
127
- return _hubGet('/a2a/atp/merchant/tier?node_id=' + encodeURIComponent(nid));
206
+ const q = '?node_id=' + encodeURIComponent(nid);
207
+ return _get('/atp/merchant/tier' + q, '/a2a/atp/merchant/tier' + q);
128
208
  }
129
209
 
130
210
  /**
@@ -132,7 +212,8 @@ function getMerchantTier(nodeId) {
132
212
  * @param {string} orderId
133
213
  */
134
214
  function getOrderStatus(orderId) {
135
- return _hubGet('/a2a/atp/order/' + encodeURIComponent(orderId));
215
+ const suffix = '/' + encodeURIComponent(orderId);
216
+ return _get('/atp/order' + suffix, '/a2a/atp/order' + suffix);
136
217
  }
137
218
 
138
219
  /**
@@ -148,14 +229,15 @@ function listProofs(opts) {
148
229
  if (opts && opts.role) params.set('role', opts.role);
149
230
  if (opts && opts.status) params.set('status', opts.status);
150
231
  if (opts && opts.limit) params.set('limit', String(opts.limit));
151
- return _hubGet('/a2a/atp/proofs?' + params.toString());
232
+ const q = '?' + params.toString();
233
+ return _get('/atp/proofs' + q, '/a2a/atp/proofs' + q);
152
234
  }
153
235
 
154
236
  /**
155
237
  * GET /a2a/atp/policy -- get ATP policy config
156
238
  */
157
239
  function getAtpPolicy() {
158
- return _hubGet('/a2a/atp/policy');
240
+ return _get('/atp/policy', '/a2a/atp/policy');
159
241
  }
160
242
 
161
243
  module.exports = {
@@ -168,4 +250,6 @@ module.exports = {
168
250
  getOrderStatus,
169
251
  listProofs,
170
252
  getAtpPolicy,
253
+ // exported for tests only
254
+ _isProxyMode: _isProxyMode,
171
255
  };
package/src/atp/index.js CHANGED
@@ -7,12 +7,16 @@
7
7
  // consumerAgent - ready-to-use consumer agent template
8
8
  // serviceHelper - service publishing helper
9
9
  // defaultHandler - default order handler + config helpers for auto-ATP
10
+ // autoBuyer - opt-in capability-gap auto order helper with budget caps
11
+ // cli - parsers and runners for the `buy`/`orders`/`verify` subcommands
10
12
 
11
13
  const hubClient = require('./hubClient');
12
14
  const merchantAgent = require('./merchantAgent');
13
15
  const consumerAgent = require('./consumerAgent');
14
16
  const serviceHelper = require('./serviceHelper');
15
17
  const defaultHandler = require('./defaultHandler');
18
+ const autoBuyer = require('./autoBuyer');
19
+ const cli = require('./cli');
16
20
 
17
21
  module.exports = {
18
22
  hubClient,
@@ -20,4 +24,6 @@ module.exports = {
20
24
  consumerAgent,
21
25
  serviceHelper,
22
26
  defaultHandler,
27
+ autoBuyer,
28
+ cli,
23
29
  };