@agirails/sdk 2.6.0 → 3.0.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.
Files changed (267) hide show
  1. package/README.md +1 -1
  2. package/bin/agirails +10 -0
  3. package/dist/ACTPClient.d.ts +9 -4
  4. package/dist/ACTPClient.d.ts.map +1 -1
  5. package/dist/ACTPClient.js +12 -8
  6. package/dist/ACTPClient.js.map +1 -1
  7. package/dist/abi/ACTPKernel.json +87 -6
  8. package/dist/adapters/BaseAdapter.d.ts +3 -3
  9. package/dist/adapters/BaseAdapter.js +3 -3
  10. package/dist/adapters/BasicAdapter.d.ts +1 -1
  11. package/dist/adapters/BasicAdapter.js +2 -2
  12. package/dist/adapters/BasicAdapter.js.map +1 -1
  13. package/dist/adapters/StandardAdapter.d.ts +30 -8
  14. package/dist/adapters/StandardAdapter.d.ts.map +1 -1
  15. package/dist/adapters/StandardAdapter.js +34 -9
  16. package/dist/adapters/StandardAdapter.js.map +1 -1
  17. package/dist/adapters/X402Adapter.d.ts.map +1 -1
  18. package/dist/adapters/X402Adapter.js +14 -12
  19. package/dist/adapters/X402Adapter.js.map +1 -1
  20. package/dist/api/agirailsApp.d.ts +197 -0
  21. package/dist/api/agirailsApp.d.ts.map +1 -0
  22. package/dist/api/agirailsApp.js +175 -0
  23. package/dist/api/agirailsApp.js.map +1 -0
  24. package/dist/cli/agirails.d.ts +10 -0
  25. package/dist/cli/agirails.d.ts.map +1 -0
  26. package/dist/cli/agirails.js +187 -0
  27. package/dist/cli/agirails.js.map +1 -0
  28. package/dist/cli/commands/autopublish.d.ts +13 -0
  29. package/dist/cli/commands/autopublish.d.ts.map +1 -0
  30. package/dist/cli/commands/autopublish.js +156 -0
  31. package/dist/cli/commands/autopublish.js.map +1 -0
  32. package/dist/cli/commands/batch.js +1 -1
  33. package/dist/cli/commands/claim-code.d.ts +11 -0
  34. package/dist/cli/commands/claim-code.d.ts.map +1 -0
  35. package/dist/cli/commands/claim-code.js +160 -0
  36. package/dist/cli/commands/claim-code.js.map +1 -0
  37. package/dist/cli/commands/claim.d.ts +17 -0
  38. package/dist/cli/commands/claim.d.ts.map +1 -0
  39. package/dist/cli/commands/claim.js +104 -0
  40. package/dist/cli/commands/claim.js.map +1 -0
  41. package/dist/cli/commands/config.js +1 -1
  42. package/dist/cli/commands/config.js.map +1 -1
  43. package/dist/cli/commands/find.d.ts +23 -0
  44. package/dist/cli/commands/find.d.ts.map +1 -0
  45. package/dist/cli/commands/find.js +230 -0
  46. package/dist/cli/commands/find.js.map +1 -0
  47. package/dist/cli/commands/health.d.ts +16 -0
  48. package/dist/cli/commands/health.d.ts.map +1 -0
  49. package/dist/cli/commands/health.js +287 -0
  50. package/dist/cli/commands/health.js.map +1 -0
  51. package/dist/cli/commands/init.d.ts.map +1 -1
  52. package/dist/cli/commands/init.js +42 -13
  53. package/dist/cli/commands/init.js.map +1 -1
  54. package/dist/cli/commands/negotiate.d.ts +11 -0
  55. package/dist/cli/commands/negotiate.d.ts.map +1 -0
  56. package/dist/cli/commands/negotiate.js +192 -0
  57. package/dist/cli/commands/negotiate.js.map +1 -0
  58. package/dist/cli/commands/publish.d.ts.map +1 -1
  59. package/dist/cli/commands/publish.js +310 -17
  60. package/dist/cli/commands/publish.js.map +1 -1
  61. package/dist/cli/commands/pull.d.ts +7 -3
  62. package/dist/cli/commands/pull.d.ts.map +1 -1
  63. package/dist/cli/commands/pull.js +105 -13
  64. package/dist/cli/commands/pull.js.map +1 -1
  65. package/dist/cli/commands/receipt.d.ts +31 -0
  66. package/dist/cli/commands/receipt.d.ts.map +1 -0
  67. package/dist/cli/commands/receipt.js +92 -0
  68. package/dist/cli/commands/receipt.js.map +1 -0
  69. package/dist/cli/commands/test.d.ts +15 -0
  70. package/dist/cli/commands/test.d.ts.map +1 -0
  71. package/dist/cli/commands/test.js +176 -0
  72. package/dist/cli/commands/test.js.map +1 -0
  73. package/dist/cli/index.js +19 -0
  74. package/dist/cli/index.js.map +1 -1
  75. package/dist/cli/testjobs/index.d.ts +18 -0
  76. package/dist/cli/testjobs/index.d.ts.map +1 -0
  77. package/dist/cli/testjobs/index.js +45 -0
  78. package/dist/cli/testjobs/index.js.map +1 -0
  79. package/dist/cli/testjobs/templates/automation.d.ts +3 -0
  80. package/dist/cli/testjobs/templates/automation.d.ts.map +1 -0
  81. package/dist/cli/testjobs/templates/automation.js +32 -0
  82. package/dist/cli/testjobs/templates/automation.js.map +1 -0
  83. package/dist/cli/testjobs/templates/code-review.d.ts +3 -0
  84. package/dist/cli/testjobs/templates/code-review.d.ts.map +1 -0
  85. package/dist/cli/testjobs/templates/code-review.js +27 -0
  86. package/dist/cli/testjobs/templates/code-review.js.map +1 -0
  87. package/dist/cli/testjobs/templates/content-writing.d.ts +3 -0
  88. package/dist/cli/testjobs/templates/content-writing.d.ts.map +1 -0
  89. package/dist/cli/testjobs/templates/content-writing.js +20 -0
  90. package/dist/cli/testjobs/templates/content-writing.js.map +1 -0
  91. package/dist/cli/testjobs/templates/data-analysis.d.ts +3 -0
  92. package/dist/cli/testjobs/templates/data-analysis.d.ts.map +1 -0
  93. package/dist/cli/testjobs/templates/data-analysis.js +34 -0
  94. package/dist/cli/testjobs/templates/data-analysis.js.map +1 -0
  95. package/dist/cli/testjobs/templates/generic.d.ts +3 -0
  96. package/dist/cli/testjobs/templates/generic.d.ts.map +1 -0
  97. package/dist/cli/testjobs/templates/generic.js +17 -0
  98. package/dist/cli/testjobs/templates/generic.js.map +1 -0
  99. package/dist/cli/testjobs/templates/security-audit.d.ts +3 -0
  100. package/dist/cli/testjobs/templates/security-audit.d.ts.map +1 -0
  101. package/dist/cli/testjobs/templates/security-audit.js +30 -0
  102. package/dist/cli/testjobs/templates/security-audit.js.map +1 -0
  103. package/dist/cli/testjobs/templates/testing.d.ts +3 -0
  104. package/dist/cli/testjobs/templates/testing.d.ts.map +1 -0
  105. package/dist/cli/testjobs/templates/testing.js +29 -0
  106. package/dist/cli/testjobs/templates/testing.js.map +1 -0
  107. package/dist/cli/testjobs/templates/translation.d.ts +3 -0
  108. package/dist/cli/testjobs/templates/translation.d.ts.map +1 -0
  109. package/dist/cli/testjobs/templates/translation.js +16 -0
  110. package/dist/cli/testjobs/templates/translation.js.map +1 -0
  111. package/dist/cli/testjobs/types.d.ts +16 -0
  112. package/dist/cli/testjobs/types.d.ts.map +1 -0
  113. package/dist/cli/testjobs/types.js +8 -0
  114. package/dist/cli/testjobs/types.js.map +1 -0
  115. package/dist/cli/utils/client.js +1 -1
  116. package/dist/cli/utils/client.js.map +1 -1
  117. package/dist/cli/utils/config.d.ts +12 -0
  118. package/dist/cli/utils/config.d.ts.map +1 -1
  119. package/dist/cli/utils/config.js +29 -2
  120. package/dist/cli/utils/config.js.map +1 -1
  121. package/dist/config/agirailsmd.d.ts +1 -1
  122. package/dist/config/agirailsmd.d.ts.map +1 -1
  123. package/dist/config/agirailsmd.js +3 -0
  124. package/dist/config/agirailsmd.js.map +1 -1
  125. package/dist/config/agirailsmdV4.d.ts +82 -0
  126. package/dist/config/agirailsmdV4.d.ts.map +1 -0
  127. package/dist/config/agirailsmdV4.js +254 -0
  128. package/dist/config/agirailsmdV4.js.map +1 -0
  129. package/dist/config/defaults.d.ts +50 -0
  130. package/dist/config/defaults.d.ts.map +1 -0
  131. package/dist/config/defaults.js +77 -0
  132. package/dist/config/defaults.js.map +1 -0
  133. package/dist/config/networks.d.ts +1 -0
  134. package/dist/config/networks.d.ts.map +1 -1
  135. package/dist/config/networks.js +16 -13
  136. package/dist/config/networks.js.map +1 -1
  137. package/dist/config/publishPipeline.d.ts.map +1 -1
  138. package/dist/config/publishPipeline.js +4 -0
  139. package/dist/config/publishPipeline.js.map +1 -1
  140. package/dist/config/slugUtils.d.ts +28 -0
  141. package/dist/config/slugUtils.d.ts.map +1 -0
  142. package/dist/config/slugUtils.js +51 -0
  143. package/dist/config/slugUtils.js.map +1 -0
  144. package/dist/level0/ServiceDirectory.d.ts +6 -6
  145. package/dist/level0/ServiceDirectory.js +11 -11
  146. package/dist/level0/ServiceDirectory.js.map +1 -1
  147. package/dist/level1/Agent.d.ts +10 -10
  148. package/dist/level1/Agent.d.ts.map +1 -1
  149. package/dist/level1/Agent.js +45 -29
  150. package/dist/level1/Agent.js.map +1 -1
  151. package/dist/level1/pricing/PriceCalculator.js +2 -2
  152. package/dist/level1/pricing/PriceCalculator.js.map +1 -1
  153. package/dist/negotiation/BuyerOrchestrator.d.ts +108 -0
  154. package/dist/negotiation/BuyerOrchestrator.d.ts.map +1 -0
  155. package/dist/negotiation/BuyerOrchestrator.js +377 -0
  156. package/dist/negotiation/BuyerOrchestrator.js.map +1 -0
  157. package/dist/negotiation/DecisionEngine.d.ts +44 -0
  158. package/dist/negotiation/DecisionEngine.d.ts.map +1 -0
  159. package/dist/negotiation/DecisionEngine.js +116 -0
  160. package/dist/negotiation/DecisionEngine.js.map +1 -0
  161. package/dist/negotiation/PolicyEngine.d.ts +126 -0
  162. package/dist/negotiation/PolicyEngine.d.ts.map +1 -0
  163. package/dist/negotiation/PolicyEngine.js +265 -0
  164. package/dist/negotiation/PolicyEngine.js.map +1 -0
  165. package/dist/negotiation/SessionStore.d.ts +57 -0
  166. package/dist/negotiation/SessionStore.d.ts.map +1 -0
  167. package/dist/negotiation/SessionStore.js +179 -0
  168. package/dist/negotiation/SessionStore.js.map +1 -0
  169. package/dist/negotiation/index.d.ts +9 -0
  170. package/dist/negotiation/index.d.ts.map +1 -0
  171. package/dist/negotiation/index.js +12 -0
  172. package/dist/negotiation/index.js.map +1 -0
  173. package/dist/protocol/ACTPKernel.d.ts +32 -4
  174. package/dist/protocol/ACTPKernel.d.ts.map +1 -1
  175. package/dist/protocol/ACTPKernel.js +70 -16
  176. package/dist/protocol/ACTPKernel.js.map +1 -1
  177. package/dist/protocol/AgentRegistry.js +2 -2
  178. package/dist/protocol/AgentRegistry.js.map +1 -1
  179. package/dist/protocol/DIDResolver.js +2 -2
  180. package/dist/protocol/DIDResolver.js.map +1 -1
  181. package/dist/protocol/EASHelper.d.ts +2 -2
  182. package/dist/protocol/EASHelper.js +5 -5
  183. package/dist/protocol/EASHelper.js.map +1 -1
  184. package/dist/protocol/EscrowVault.d.ts +2 -2
  185. package/dist/protocol/EscrowVault.js +4 -4
  186. package/dist/protocol/EscrowVault.js.map +1 -1
  187. package/dist/protocol/EventMonitor.d.ts +4 -4
  188. package/dist/protocol/EventMonitor.js +5 -5
  189. package/dist/protocol/EventMonitor.js.map +1 -1
  190. package/dist/protocol/MessageSigner.d.ts +5 -5
  191. package/dist/protocol/MessageSigner.js +8 -8
  192. package/dist/protocol/MessageSigner.js.map +1 -1
  193. package/dist/protocol/ProofGenerator.d.ts +4 -4
  194. package/dist/protocol/ProofGenerator.js +6 -6
  195. package/dist/protocol/ProofGenerator.js.map +1 -1
  196. package/dist/runtime/BlockchainRuntime.d.ts +24 -14
  197. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
  198. package/dist/runtime/BlockchainRuntime.js +60 -45
  199. package/dist/runtime/BlockchainRuntime.js.map +1 -1
  200. package/dist/runtime/IACTPRuntime.d.ts +12 -1
  201. package/dist/runtime/IACTPRuntime.d.ts.map +1 -1
  202. package/dist/runtime/MockRuntime.d.ts +22 -9
  203. package/dist/runtime/MockRuntime.d.ts.map +1 -1
  204. package/dist/runtime/MockRuntime.js +76 -24
  205. package/dist/runtime/MockRuntime.js.map +1 -1
  206. package/dist/runtime/MockStateManager.js +2 -2
  207. package/dist/runtime/MockStateManager.js.map +1 -1
  208. package/dist/runtime/types/MockState.d.ts +1 -1
  209. package/dist/types/erc8004.d.ts +2 -2
  210. package/dist/types/erc8004.d.ts.map +1 -1
  211. package/dist/types/erc8004.js +4 -1
  212. package/dist/types/erc8004.js.map +1 -1
  213. package/dist/types/state.d.ts +1 -1
  214. package/dist/types/state.js +1 -1
  215. package/dist/types/transaction.d.ts +4 -0
  216. package/dist/types/transaction.d.ts.map +1 -1
  217. package/dist/types/x402.d.ts +17 -9
  218. package/dist/types/x402.d.ts.map +1 -1
  219. package/dist/types/x402.js +9 -9
  220. package/dist/types/x402.js.map +1 -1
  221. package/dist/utils/ErrorRecoveryGuide.d.ts +1 -1
  222. package/dist/utils/ErrorRecoveryGuide.js +1 -1
  223. package/dist/utils/Helpers.d.ts +6 -6
  224. package/dist/utils/Helpers.js +7 -7
  225. package/dist/utils/Helpers.js.map +1 -1
  226. package/dist/utils/IPFSClient.d.ts +7 -7
  227. package/dist/utils/IPFSClient.js +9 -9
  228. package/dist/utils/IPFSClient.js.map +1 -1
  229. package/dist/utils/Logger.d.ts +4 -4
  230. package/dist/utils/Logger.js +8 -8
  231. package/dist/utils/Logger.js.map +1 -1
  232. package/dist/utils/NonceManager.d.ts +9 -9
  233. package/dist/utils/NonceManager.js +19 -19
  234. package/dist/utils/NonceManager.js.map +1 -1
  235. package/dist/utils/RateLimiter.d.ts +10 -10
  236. package/dist/utils/RateLimiter.d.ts.map +1 -1
  237. package/dist/utils/RateLimiter.js +22 -22
  238. package/dist/utils/RateLimiter.js.map +1 -1
  239. package/dist/utils/ReceivedNonceTracker.d.ts +10 -10
  240. package/dist/utils/ReceivedNonceTracker.js +20 -20
  241. package/dist/utils/ReceivedNonceTracker.js.map +1 -1
  242. package/dist/utils/SDKLifecycle.d.ts +3 -3
  243. package/dist/utils/SDKLifecycle.js +7 -7
  244. package/dist/utils/SDKLifecycle.js.map +1 -1
  245. package/dist/utils/SecureNonce.d.ts +1 -1
  246. package/dist/utils/SecureNonce.js +1 -1
  247. package/dist/utils/Semaphore.d.ts +2 -2
  248. package/dist/utils/Semaphore.js +2 -2
  249. package/dist/utils/UsedAttestationTracker.d.ts +13 -13
  250. package/dist/utils/UsedAttestationTracker.js +20 -20
  251. package/dist/utils/UsedAttestationTracker.js.map +1 -1
  252. package/dist/utils/security.d.ts +3 -3
  253. package/dist/utils/security.js +4 -4
  254. package/dist/utils/security.js.map +1 -1
  255. package/dist/utils/validation.d.ts +4 -4
  256. package/dist/utils/validation.js +9 -9
  257. package/dist/utils/validation.js.map +1 -1
  258. package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
  259. package/dist/wallet/AutoWalletProvider.js +2 -1
  260. package/dist/wallet/AutoWalletProvider.js.map +1 -1
  261. package/dist/wallet/IWalletProvider.d.ts +2 -0
  262. package/dist/wallet/IWalletProvider.d.ts.map +1 -1
  263. package/dist/wallet/aa/TransactionBatcher.d.ts +22 -2
  264. package/dist/wallet/aa/TransactionBatcher.d.ts.map +1 -1
  265. package/dist/wallet/aa/TransactionBatcher.js +51 -9
  266. package/dist/wallet/aa/TransactionBatcher.js.map +1 -1
  267. package/package.json +6 -12
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ /**
3
+ * BuyerOrchestrator — Autonomous buyer-side negotiation orchestrator.
4
+ *
5
+ * Flow:
6
+ * 1. Discover candidates (via agirails.app API)
7
+ * 2. Score with DecisionEngine (weighted ranking)
8
+ * 3. Validate with PolicyEngine (5 guardrails)
9
+ * 4. For each candidate (up to rounds_max):
10
+ * a. createTransaction → INITIATED
11
+ * b. Poll for QUOTED state (within quote_ttl)
12
+ * c. Validate quote against policy
13
+ * d. Accept → linkEscrow → COMMITTED
14
+ * e. OR reject → try next candidate
15
+ * 5. Track everything via SessionStore
16
+ *
17
+ * Accepts ACTPClient for on-chain operations. Caller manages lifecycle.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.BuyerOrchestrator = void 0;
21
+ const agirailsApp_1 = require("../api/agirailsApp");
22
+ const PolicyEngine_1 = require("./PolicyEngine");
23
+ const DecisionEngine_1 = require("./DecisionEngine");
24
+ const SessionStore_1 = require("./SessionStore");
25
+ // ============================================================================
26
+ // BuyerOrchestrator
27
+ // ============================================================================
28
+ class BuyerOrchestrator {
29
+ constructor(policy, runtime, requesterAddress, actpDir) {
30
+ this.policy = policy;
31
+ this.runtime = runtime;
32
+ this.requesterAddress = requesterAddress;
33
+ this.policyEngine = new PolicyEngine_1.PolicyEngine(policy, actpDir);
34
+ this.decisionEngine = new DecisionEngine_1.DecisionEngine(policy.selection.weights);
35
+ this.sessionStore = new SessionStore_1.SessionStore(actpDir);
36
+ }
37
+ /**
38
+ * Execute the full negotiation flow.
39
+ */
40
+ async negotiate(config = {}) {
41
+ const pollInterval = config.pollIntervalMs ?? 3000;
42
+ const emit = config.onProgress ?? (() => { });
43
+ // Create session
44
+ const session = this.sessionStore.create(this.policy.task);
45
+ const rounds = [];
46
+ try {
47
+ return await this._negotiate(session, rounds, config, pollInterval, emit);
48
+ }
49
+ catch (err) {
50
+ // Guarantee session reaches terminal status on any uncaught throw
51
+ const currentSession = this.sessionStore.get(session.commerce_session_id);
52
+ if (currentSession && currentSession.status === 'active') {
53
+ this.sessionStore.updateStatus(session.commerce_session_id, 'failed');
54
+ }
55
+ throw err;
56
+ }
57
+ }
58
+ async _negotiate(session, rounds, config, pollInterval, emit) {
59
+ // 1. Discover candidates
60
+ const discoverParams = {
61
+ search: this.policy.task,
62
+ sort: 'reputation',
63
+ limit: 20,
64
+ maxPrice: this.policy.constraints.max_unit_price.amount,
65
+ ...config.discover,
66
+ };
67
+ const discovered = await (0, agirailsApp_1.discoverAgents)(discoverParams);
68
+ emit({ type: 'discovery', candidates: discovered.agents.length });
69
+ if (discovered.agents.length === 0) {
70
+ emit({ type: 'complete', success: false, reason: 'No candidates found' });
71
+ this.sessionStore.updateStatus(session.commerce_session_id, 'failed');
72
+ return {
73
+ success: false,
74
+ commerce_session_id: session.commerce_session_id,
75
+ rounds_used: 0,
76
+ reason: 'No candidates found',
77
+ rounds,
78
+ };
79
+ }
80
+ // 2. Score candidates with DecisionEngine
81
+ const candidateStats = this.mapToCandidateStats(discovered.agents);
82
+ const ranked = this.decisionEngine.rank(candidateStats, this.policy.constraints.max_unit_price.amount);
83
+ emit({ type: 'scoring', ranked: ranked.length });
84
+ if (ranked.length === 0) {
85
+ emit({ type: 'complete', success: false, reason: 'No candidates within budget' });
86
+ this.sessionStore.updateStatus(session.commerce_session_id, 'failed');
87
+ return {
88
+ success: false,
89
+ commerce_session_id: session.commerce_session_id,
90
+ rounds_used: 0,
91
+ reason: 'No candidates within budget after scoring',
92
+ rounds,
93
+ };
94
+ }
95
+ // Dry-run: return ranked candidates without creating transactions
96
+ if (config.dryRun) {
97
+ this.sessionStore.updateStatus(session.commerce_session_id, 'completed');
98
+ emit({ type: 'complete', success: true, reason: 'Dry run complete' });
99
+ return {
100
+ success: true,
101
+ commerce_session_id: session.commerce_session_id,
102
+ rounds_used: 0,
103
+ reason: `Dry run: ${ranked.length} candidates ranked`,
104
+ rounds: ranked.map((c, i) => ({
105
+ round: i + 1,
106
+ provider_slug: c.slug,
107
+ provider_address: this.findAgentAddress(discovered.agents, c.slug),
108
+ action: 'accepted',
109
+ reason: `Score: ${c.score.toFixed(3)}`,
110
+ })),
111
+ };
112
+ }
113
+ // 3. Try candidates up to rounds_max
114
+ const maxRounds = Math.min(this.policy.negotiation.rounds_max, ranked.length);
115
+ const quoteTtlSeconds = PolicyEngine_1.PolicyEngine.parseTtl(this.policy.negotiation.quote_ttl);
116
+ // Price tracking for deadlock detection (PRD-5B)
117
+ const priceHistory = [];
118
+ let deadlockDetected = false;
119
+ for (let round = 0; round < maxRounds; round++) {
120
+ const candidate = ranked[round];
121
+ const providerAddress = this.findAgentAddress(discovered.agents, candidate.slug);
122
+ emit({ type: 'round_start', round: round + 1, provider: candidate.slug });
123
+ this.sessionStore.recordAttempt(session.commerce_session_id, candidate.slug);
124
+ // 3a. Pre-validate with PolicyEngine
125
+ const offer = {
126
+ provider: candidate.slug,
127
+ unit_price: this.findAgentPrice(discovered.agents, candidate.slug),
128
+ currency: this.policy.constraints.max_unit_price.currency,
129
+ unit: this.policy.constraints.max_unit_price.unit,
130
+ reputation_score: this.findAgentReputation(discovered.agents, candidate.slug),
131
+ commerce_session_id: session.commerce_session_id,
132
+ expires_at: Math.floor(Date.now() / 1000) + quoteTtlSeconds,
133
+ final_offer: deadlockDetected,
134
+ };
135
+ const validation = this.policyEngine.validate(offer);
136
+ if (!validation.allowed) {
137
+ const reason = validation.violations.map(v => `${v.rule}: ${v.detail}`).join('; ');
138
+ rounds.push({
139
+ round: round + 1,
140
+ provider_slug: candidate.slug,
141
+ provider_address: providerAddress,
142
+ action: 'rejected',
143
+ reason: `Policy violation: ${reason}`,
144
+ });
145
+ emit({ type: 'round_end', round: round + 1, action: 'rejected', reason });
146
+ continue;
147
+ }
148
+ // 3b. Create transaction
149
+ let txId;
150
+ try {
151
+ const amount = this.toBaseUnits(offer.unit_price);
152
+ txId = await this.runtime.createTransaction({
153
+ provider: providerAddress,
154
+ requester: this.requesterAddress,
155
+ amount,
156
+ deadline: Math.floor(Date.now() / 1000) + quoteTtlSeconds + 3600, // quote TTL + 1h buffer
157
+ serviceDescription: JSON.stringify({ service: this.policy.task, session: session.commerce_session_id }),
158
+ });
159
+ }
160
+ catch (err) {
161
+ const reason = err instanceof Error ? err.message : String(err);
162
+ rounds.push({
163
+ round: round + 1,
164
+ provider_slug: candidate.slug,
165
+ provider_address: providerAddress,
166
+ action: 'error',
167
+ reason: `createTransaction failed: ${reason}`,
168
+ });
169
+ emit({ type: 'round_end', round: round + 1, action: 'error', reason });
170
+ continue;
171
+ }
172
+ // 3c. Wait for quote or direct commit (ACTP allows INITIATED → COMMITTED fast path)
173
+ emit({ type: 'waiting_quote', txId, ttlSeconds: quoteTtlSeconds });
174
+ const reachedState = await this.waitForState(txId, ['QUOTED', 'COMMITTED'], quoteTtlSeconds * 1000, pollInterval);
175
+ if (!reachedState) {
176
+ // Timeout or cancelled — cancel and try next
177
+ try {
178
+ await this.runtime.transitionState(txId, 'CANCELLED');
179
+ }
180
+ catch {
181
+ // Best-effort cancel
182
+ }
183
+ rounds.push({
184
+ round: round + 1,
185
+ provider_slug: candidate.slug,
186
+ provider_address: providerAddress,
187
+ action: 'timeout',
188
+ reason: `No quote within ${quoteTtlSeconds}s`,
189
+ tx_id: txId,
190
+ });
191
+ emit({ type: 'round_end', round: round + 1, action: 'timeout', reason: 'Quote TTL expired' });
192
+ continue;
193
+ }
194
+ emit({ type: 'quote_received', txId });
195
+ // 3d. Read quoted price from on-chain for tracking (PRD-5B)
196
+ let quotedPrice;
197
+ try {
198
+ const quotedTx = await this.runtime.getTransaction(txId);
199
+ if (quotedTx && quotedTx.amount) {
200
+ const rawAmount = typeof quotedTx.amount === 'string' ? parseFloat(quotedTx.amount) : quotedTx.amount;
201
+ quotedPrice = rawAmount / 1000000; // Convert base units to USDC
202
+ priceHistory.push(quotedPrice);
203
+ // Deadlock detection: if 2+ consecutive identical prices, flag deadlock
204
+ if (priceHistory.length >= 2) {
205
+ const last = priceHistory[priceHistory.length - 1];
206
+ const prev = priceHistory[priceHistory.length - 2];
207
+ if (last === prev) {
208
+ deadlockDetected = true;
209
+ }
210
+ }
211
+ }
212
+ }
213
+ catch {
214
+ // Non-fatal — price tracking is best-effort
215
+ }
216
+ // 3e. Reserve budget and link escrow (or recognize already-committed).
217
+ // ACTP invariant: tx.amount is immutable (set at createTransaction).
218
+ // Policy was already validated pre-round, so offer.unit_price
219
+ // is the correct amount for both reservation and escrow.
220
+ if (reachedState === 'COMMITTED') {
221
+ // COMMITTED is terminal on-chain — this is a success regardless of local ledger state.
222
+ // Best-effort reserve for local budget tracking; failure is non-fatal.
223
+ try {
224
+ this.policyEngine.reserve(session.commerce_session_id, offer.unit_price, offer.currency);
225
+ }
226
+ catch {
227
+ // Local ledger out of sync — log but don't fail the already-committed tx
228
+ }
229
+ this.sessionStore.linkTransaction(session.commerce_session_id, txId, candidate.slug);
230
+ const reason = 'Provider already committed, escrow recognized';
231
+ rounds.push({
232
+ round: round + 1,
233
+ provider_slug: candidate.slug,
234
+ provider_address: providerAddress,
235
+ action: 'accepted',
236
+ reason,
237
+ tx_id: txId,
238
+ quoted_price: quotedPrice,
239
+ });
240
+ emit({ type: 'round_end', round: round + 1, action: 'accepted', reason });
241
+ emit({ type: 'complete', success: true, reason: 'Negotiation complete' });
242
+ return {
243
+ success: true,
244
+ commerce_session_id: session.commerce_session_id,
245
+ actp_tx_id: txId,
246
+ selected_provider: candidate.slug,
247
+ rounds_used: round + 1,
248
+ reason: 'Negotiation complete — already committed',
249
+ rounds,
250
+ deadlock_detected: deadlockDetected,
251
+ };
252
+ }
253
+ // QUOTED path: reserve budget + link escrow (both must succeed, or try next candidate)
254
+ const escrowAmount = this.toBaseUnits(offer.unit_price);
255
+ try {
256
+ this.policyEngine.reserve(session.commerce_session_id, offer.unit_price, offer.currency);
257
+ await this.runtime.linkEscrow(txId, escrowAmount);
258
+ // Success
259
+ this.sessionStore.linkTransaction(session.commerce_session_id, txId, candidate.slug);
260
+ const reason = 'Quote accepted, escrow linked';
261
+ rounds.push({
262
+ round: round + 1,
263
+ provider_slug: candidate.slug,
264
+ provider_address: providerAddress,
265
+ action: 'accepted',
266
+ reason,
267
+ tx_id: txId,
268
+ quoted_price: quotedPrice,
269
+ });
270
+ emit({ type: 'round_end', round: round + 1, action: 'accepted', reason });
271
+ emit({ type: 'complete', success: true, reason: 'Negotiation complete' });
272
+ return {
273
+ success: true,
274
+ commerce_session_id: session.commerce_session_id,
275
+ actp_tx_id: txId,
276
+ selected_provider: candidate.slug,
277
+ rounds_used: round + 1,
278
+ reason: 'Negotiation complete — escrow linked',
279
+ rounds,
280
+ deadlock_detected: deadlockDetected,
281
+ };
282
+ }
283
+ catch (err) {
284
+ // Reserve or linkEscrow failed — release and try next
285
+ this.policyEngine.release(session.commerce_session_id);
286
+ const reason = err instanceof Error ? err.message : String(err);
287
+ rounds.push({
288
+ round: round + 1,
289
+ provider_slug: candidate.slug,
290
+ provider_address: providerAddress,
291
+ action: 'error',
292
+ reason: `Escrow failed: ${reason}`,
293
+ tx_id: txId,
294
+ quoted_price: quotedPrice,
295
+ });
296
+ emit({ type: 'round_end', round: round + 1, action: 'error', reason });
297
+ continue;
298
+ }
299
+ }
300
+ // All rounds exhausted
301
+ this.sessionStore.updateStatus(session.commerce_session_id, 'failed');
302
+ emit({ type: 'complete', success: false, reason: 'All candidates exhausted' });
303
+ const exhaustedReason = deadlockDetected
304
+ ? `All ${rounds.length} candidates exhausted (price deadlock detected)`
305
+ : `All ${rounds.length} candidates exhausted`;
306
+ return {
307
+ success: false,
308
+ commerce_session_id: session.commerce_session_id,
309
+ rounds_used: rounds.length,
310
+ reason: exhaustedReason,
311
+ rounds,
312
+ deadlock_detected: deadlockDetected,
313
+ };
314
+ }
315
+ // ============================================================================
316
+ // Helpers
317
+ // ============================================================================
318
+ /**
319
+ * Poll until tx reaches one of the target states.
320
+ * Returns the reached state, or null on timeout/cancelled.
321
+ * Resilient to transient RPC errors (retries until deadline).
322
+ */
323
+ async waitForState(txId, targetStates, timeoutMs, pollIntervalMs) {
324
+ const deadline = Date.now() + timeoutMs;
325
+ while (Date.now() < deadline) {
326
+ try {
327
+ const tx = await this.runtime.getTransaction(txId);
328
+ if (tx && targetStates.includes(tx.state))
329
+ return tx.state;
330
+ // Exit early if CANCELLED by provider
331
+ if (tx && tx.state === 'CANCELLED')
332
+ return null;
333
+ }
334
+ catch {
335
+ // Transient error (RPC timeout, network blip) — keep polling until deadline
336
+ }
337
+ await this.sleep(Math.min(pollIntervalMs, deadline - Date.now()));
338
+ }
339
+ return null;
340
+ }
341
+ sleep(ms) {
342
+ return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
343
+ }
344
+ mapToCandidateStats(agents) {
345
+ return agents
346
+ .filter(a => a.wallet_address && a.published_config?.pricing)
347
+ .map(a => ({
348
+ slug: a.slug,
349
+ unit_price: typeof a.published_config.pricing.amount === 'string'
350
+ ? parseFloat(a.published_config.pricing.amount)
351
+ : (a.published_config.pricing.amount ?? 0),
352
+ reputation_score: a.stats?.reputation_score ?? 0,
353
+ success_rate: a.stats?.success_rate ?? 0,
354
+ avg_completion_time_seconds: a.stats?.avg_completion_time_seconds ?? null,
355
+ completed_transactions: a.stats?.completed_transactions ?? 0,
356
+ }));
357
+ }
358
+ findAgentAddress(agents, slug) {
359
+ return agents.find(a => a.slug === slug)?.wallet_address ?? '';
360
+ }
361
+ findAgentPrice(agents, slug) {
362
+ const agent = agents.find(a => a.slug === slug);
363
+ const amount = agent?.published_config?.pricing?.amount;
364
+ if (typeof amount === 'string')
365
+ return parseFloat(amount);
366
+ return amount ?? 0;
367
+ }
368
+ findAgentReputation(agents, slug) {
369
+ return agents.find(a => a.slug === slug)?.stats?.reputation_score;
370
+ }
371
+ /** Convert a USDC amount (e.g. 0.80) to base units string (e.g. "800000") */
372
+ toBaseUnits(amount) {
373
+ return String(Math.round(amount * 1000000));
374
+ }
375
+ }
376
+ exports.BuyerOrchestrator = BuyerOrchestrator;
377
+ //# sourceMappingURL=BuyerOrchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuyerOrchestrator.js","sourceRoot":"","sources":["../../src/negotiation/BuyerOrchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * DecisionEngine — Weighted scoring for agent candidate ranking.
3
+ *
4
+ * Scores policy-valid candidates using configurable weights:
5
+ * score = w_quality * quality + w_price * price + w_speed * speed + w_reliability * reliability
6
+ *
7
+ * Default weights: quality=0.35, price=0.30, speed=0.20, reliability=0.15
8
+ *
9
+ * Tie-breakers: lower price → better on-time rate → earlier in discovery results.
10
+ */
11
+ export interface ScoringWeights {
12
+ quality?: number;
13
+ price?: number;
14
+ speed?: number;
15
+ reliability?: number;
16
+ }
17
+ export interface CandidateStats {
18
+ slug: string;
19
+ unit_price: number;
20
+ reputation_score: number;
21
+ success_rate: number;
22
+ avg_completion_time_seconds: number | null;
23
+ completed_transactions: number;
24
+ }
25
+ export interface ScoredCandidate {
26
+ slug: string;
27
+ score: number;
28
+ breakdown: {
29
+ quality: number;
30
+ price: number;
31
+ speed: number;
32
+ reliability: number;
33
+ };
34
+ }
35
+ export declare class DecisionEngine {
36
+ private weights;
37
+ constructor(weights?: ScoringWeights);
38
+ /**
39
+ * Score and rank candidates. Returns sorted by score descending.
40
+ * If maxPrice is provided, candidates exceeding it are filtered out.
41
+ */
42
+ rank(candidates: CandidateStats[], maxPrice?: number): ScoredCandidate[];
43
+ }
44
+ //# sourceMappingURL=DecisionEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionEngine.d.ts","sourceRoot":"","sources":["../../src/negotiation/DecisionEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAiBD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA2B;gBAE9B,OAAO,CAAC,EAAE,cAAc;IAkBpC;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE;CAgFzE"}
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ /**
3
+ * DecisionEngine — Weighted scoring for agent candidate ranking.
4
+ *
5
+ * Scores policy-valid candidates using configurable weights:
6
+ * score = w_quality * quality + w_price * price + w_speed * speed + w_reliability * reliability
7
+ *
8
+ * Default weights: quality=0.35, price=0.30, speed=0.20, reliability=0.15
9
+ *
10
+ * Tie-breakers: lower price → better on-time rate → earlier in discovery results.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.DecisionEngine = void 0;
14
+ // ============================================================================
15
+ // Constants
16
+ // ============================================================================
17
+ const DEFAULT_WEIGHTS = {
18
+ quality: 0.35,
19
+ price: 0.30,
20
+ speed: 0.20,
21
+ reliability: 0.15,
22
+ };
23
+ // ============================================================================
24
+ // DecisionEngine
25
+ // ============================================================================
26
+ class DecisionEngine {
27
+ constructor(weights) {
28
+ this.weights = {
29
+ quality: weights?.quality ?? DEFAULT_WEIGHTS.quality,
30
+ price: weights?.price ?? DEFAULT_WEIGHTS.price,
31
+ speed: weights?.speed ?? DEFAULT_WEIGHTS.speed,
32
+ reliability: weights?.reliability ?? DEFAULT_WEIGHTS.reliability,
33
+ };
34
+ // Normalize weights to sum to 1.0
35
+ const total = this.weights.quality + this.weights.price + this.weights.speed + this.weights.reliability;
36
+ if (total > 0 && Math.abs(total - 1.0) > 0.001) {
37
+ this.weights.quality /= total;
38
+ this.weights.price /= total;
39
+ this.weights.speed /= total;
40
+ this.weights.reliability /= total;
41
+ }
42
+ }
43
+ /**
44
+ * Score and rank candidates. Returns sorted by score descending.
45
+ * If maxPrice is provided, candidates exceeding it are filtered out.
46
+ */
47
+ rank(candidates, maxPrice) {
48
+ // Filter out over-budget candidates
49
+ const eligible = maxPrice != null
50
+ ? candidates.filter((c) => c.unit_price <= maxPrice)
51
+ : candidates;
52
+ if (eligible.length === 0)
53
+ return [];
54
+ // Compute min/max for normalization
55
+ const prices = eligible.map((c) => c.unit_price);
56
+ const times = eligible
57
+ .map((c) => c.avg_completion_time_seconds)
58
+ .filter((t) => t != null);
59
+ const minPrice = Math.min(...prices);
60
+ const maxPriceVal = Math.max(...prices);
61
+ const priceRange = maxPriceVal - minPrice;
62
+ const minTime = times.length > 0 ? Math.min(...times) : 0;
63
+ const maxTime = times.length > 0 ? Math.max(...times) : 1;
64
+ const timeRange = maxTime - minTime;
65
+ const scored = eligible.map((c) => {
66
+ // Quality: reputation_score normalized to 0-1
67
+ const quality = c.reputation_score / 100;
68
+ // Price: inverted (lower is better), normalized to 0-1
69
+ const price = priceRange > 0
70
+ ? 1 - (c.unit_price - minPrice) / priceRange
71
+ : 1; // all same price → all get max score
72
+ // Speed: inverted (faster is better), normalized to 0-1
73
+ // Agents with no completion data are penalized (0.5) vs those with data (1.0 when equal)
74
+ let speed;
75
+ if (c.avg_completion_time_seconds != null) {
76
+ speed = timeRange > 0
77
+ ? 1 - (c.avg_completion_time_seconds - minTime) / timeRange
78
+ : 1.0; // all candidates with data are equal on speed
79
+ }
80
+ else {
81
+ speed = 0.5; // no data — penalized vs agents with track record
82
+ }
83
+ // Reliability: success_rate normalized to 0-1
84
+ const reliability = c.success_rate / 100;
85
+ const score = this.weights.quality * quality +
86
+ this.weights.price * price +
87
+ this.weights.speed * speed +
88
+ this.weights.reliability * reliability;
89
+ return {
90
+ slug: c.slug,
91
+ score,
92
+ breakdown: { quality, price, speed, reliability },
93
+ };
94
+ });
95
+ // Sort by score descending, then tie-breakers
96
+ scored.sort((a, b) => {
97
+ if (Math.abs(b.score - a.score) > 0.001)
98
+ return b.score - a.score;
99
+ // Tie-breaker 1: lower price
100
+ const aCandidate = eligible.find((c) => c.slug === a.slug);
101
+ const bCandidate = eligible.find((c) => c.slug === b.slug);
102
+ if (aCandidate.unit_price !== bCandidate.unit_price) {
103
+ return aCandidate.unit_price - bCandidate.unit_price;
104
+ }
105
+ // Tie-breaker 2: higher success rate (on-time proxy)
106
+ if (aCandidate.success_rate !== bCandidate.success_rate) {
107
+ return bCandidate.success_rate - aCandidate.success_rate;
108
+ }
109
+ // Tie-breaker 3: original order (earlier in discovery results)
110
+ return 0;
111
+ });
112
+ return scored;
113
+ }
114
+ }
115
+ exports.DecisionEngine = DecisionEngine;
116
+ //# sourceMappingURL=DecisionEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionEngine.js","sourceRoot":"","sources":["../../src/negotiation/DecisionEngine.ts"],"names":[],"mappings":"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"}