@agirails/sdk 2.7.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 (260) 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/api/agirailsApp.d.ts +197 -0
  18. package/dist/api/agirailsApp.d.ts.map +1 -0
  19. package/dist/api/agirailsApp.js +175 -0
  20. package/dist/api/agirailsApp.js.map +1 -0
  21. package/dist/cli/agirails.d.ts +10 -0
  22. package/dist/cli/agirails.d.ts.map +1 -0
  23. package/dist/cli/agirails.js +187 -0
  24. package/dist/cli/agirails.js.map +1 -0
  25. package/dist/cli/commands/autopublish.d.ts +13 -0
  26. package/dist/cli/commands/autopublish.d.ts.map +1 -0
  27. package/dist/cli/commands/autopublish.js +156 -0
  28. package/dist/cli/commands/autopublish.js.map +1 -0
  29. package/dist/cli/commands/batch.js +1 -1
  30. package/dist/cli/commands/claim-code.d.ts +11 -0
  31. package/dist/cli/commands/claim-code.d.ts.map +1 -0
  32. package/dist/cli/commands/claim-code.js +160 -0
  33. package/dist/cli/commands/claim-code.js.map +1 -0
  34. package/dist/cli/commands/claim.d.ts +17 -0
  35. package/dist/cli/commands/claim.d.ts.map +1 -0
  36. package/dist/cli/commands/claim.js +104 -0
  37. package/dist/cli/commands/claim.js.map +1 -0
  38. package/dist/cli/commands/config.js +1 -1
  39. package/dist/cli/commands/config.js.map +1 -1
  40. package/dist/cli/commands/find.d.ts +23 -0
  41. package/dist/cli/commands/find.d.ts.map +1 -0
  42. package/dist/cli/commands/find.js +230 -0
  43. package/dist/cli/commands/find.js.map +1 -0
  44. package/dist/cli/commands/health.d.ts +16 -0
  45. package/dist/cli/commands/health.d.ts.map +1 -0
  46. package/dist/cli/commands/health.js +287 -0
  47. package/dist/cli/commands/health.js.map +1 -0
  48. package/dist/cli/commands/init.d.ts.map +1 -1
  49. package/dist/cli/commands/init.js +42 -13
  50. package/dist/cli/commands/init.js.map +1 -1
  51. package/dist/cli/commands/negotiate.d.ts +11 -0
  52. package/dist/cli/commands/negotiate.d.ts.map +1 -0
  53. package/dist/cli/commands/negotiate.js +192 -0
  54. package/dist/cli/commands/negotiate.js.map +1 -0
  55. package/dist/cli/commands/publish.d.ts.map +1 -1
  56. package/dist/cli/commands/publish.js +310 -17
  57. package/dist/cli/commands/publish.js.map +1 -1
  58. package/dist/cli/commands/pull.d.ts +7 -3
  59. package/dist/cli/commands/pull.d.ts.map +1 -1
  60. package/dist/cli/commands/pull.js +105 -13
  61. package/dist/cli/commands/pull.js.map +1 -1
  62. package/dist/cli/commands/receipt.d.ts +31 -0
  63. package/dist/cli/commands/receipt.d.ts.map +1 -0
  64. package/dist/cli/commands/receipt.js +92 -0
  65. package/dist/cli/commands/receipt.js.map +1 -0
  66. package/dist/cli/commands/test.d.ts +15 -0
  67. package/dist/cli/commands/test.d.ts.map +1 -0
  68. package/dist/cli/commands/test.js +176 -0
  69. package/dist/cli/commands/test.js.map +1 -0
  70. package/dist/cli/index.js +19 -0
  71. package/dist/cli/index.js.map +1 -1
  72. package/dist/cli/testjobs/index.d.ts +18 -0
  73. package/dist/cli/testjobs/index.d.ts.map +1 -0
  74. package/dist/cli/testjobs/index.js +45 -0
  75. package/dist/cli/testjobs/index.js.map +1 -0
  76. package/dist/cli/testjobs/templates/automation.d.ts +3 -0
  77. package/dist/cli/testjobs/templates/automation.d.ts.map +1 -0
  78. package/dist/cli/testjobs/templates/automation.js +32 -0
  79. package/dist/cli/testjobs/templates/automation.js.map +1 -0
  80. package/dist/cli/testjobs/templates/code-review.d.ts +3 -0
  81. package/dist/cli/testjobs/templates/code-review.d.ts.map +1 -0
  82. package/dist/cli/testjobs/templates/code-review.js +27 -0
  83. package/dist/cli/testjobs/templates/code-review.js.map +1 -0
  84. package/dist/cli/testjobs/templates/content-writing.d.ts +3 -0
  85. package/dist/cli/testjobs/templates/content-writing.d.ts.map +1 -0
  86. package/dist/cli/testjobs/templates/content-writing.js +20 -0
  87. package/dist/cli/testjobs/templates/content-writing.js.map +1 -0
  88. package/dist/cli/testjobs/templates/data-analysis.d.ts +3 -0
  89. package/dist/cli/testjobs/templates/data-analysis.d.ts.map +1 -0
  90. package/dist/cli/testjobs/templates/data-analysis.js +34 -0
  91. package/dist/cli/testjobs/templates/data-analysis.js.map +1 -0
  92. package/dist/cli/testjobs/templates/generic.d.ts +3 -0
  93. package/dist/cli/testjobs/templates/generic.d.ts.map +1 -0
  94. package/dist/cli/testjobs/templates/generic.js +17 -0
  95. package/dist/cli/testjobs/templates/generic.js.map +1 -0
  96. package/dist/cli/testjobs/templates/security-audit.d.ts +3 -0
  97. package/dist/cli/testjobs/templates/security-audit.d.ts.map +1 -0
  98. package/dist/cli/testjobs/templates/security-audit.js +30 -0
  99. package/dist/cli/testjobs/templates/security-audit.js.map +1 -0
  100. package/dist/cli/testjobs/templates/testing.d.ts +3 -0
  101. package/dist/cli/testjobs/templates/testing.d.ts.map +1 -0
  102. package/dist/cli/testjobs/templates/testing.js +29 -0
  103. package/dist/cli/testjobs/templates/testing.js.map +1 -0
  104. package/dist/cli/testjobs/templates/translation.d.ts +3 -0
  105. package/dist/cli/testjobs/templates/translation.d.ts.map +1 -0
  106. package/dist/cli/testjobs/templates/translation.js +16 -0
  107. package/dist/cli/testjobs/templates/translation.js.map +1 -0
  108. package/dist/cli/testjobs/types.d.ts +16 -0
  109. package/dist/cli/testjobs/types.d.ts.map +1 -0
  110. package/dist/cli/testjobs/types.js +8 -0
  111. package/dist/cli/testjobs/types.js.map +1 -0
  112. package/dist/cli/utils/client.js +1 -1
  113. package/dist/cli/utils/client.js.map +1 -1
  114. package/dist/cli/utils/config.d.ts +12 -0
  115. package/dist/cli/utils/config.d.ts.map +1 -1
  116. package/dist/cli/utils/config.js +29 -2
  117. package/dist/cli/utils/config.js.map +1 -1
  118. package/dist/config/agirailsmd.d.ts +1 -1
  119. package/dist/config/agirailsmd.d.ts.map +1 -1
  120. package/dist/config/agirailsmd.js +3 -0
  121. package/dist/config/agirailsmd.js.map +1 -1
  122. package/dist/config/agirailsmdV4.d.ts +82 -0
  123. package/dist/config/agirailsmdV4.d.ts.map +1 -0
  124. package/dist/config/agirailsmdV4.js +254 -0
  125. package/dist/config/agirailsmdV4.js.map +1 -0
  126. package/dist/config/defaults.d.ts +50 -0
  127. package/dist/config/defaults.d.ts.map +1 -0
  128. package/dist/config/defaults.js +77 -0
  129. package/dist/config/defaults.js.map +1 -0
  130. package/dist/config/networks.d.ts +1 -0
  131. package/dist/config/networks.d.ts.map +1 -1
  132. package/dist/config/networks.js +16 -13
  133. package/dist/config/networks.js.map +1 -1
  134. package/dist/config/publishPipeline.d.ts.map +1 -1
  135. package/dist/config/publishPipeline.js +4 -0
  136. package/dist/config/publishPipeline.js.map +1 -1
  137. package/dist/config/slugUtils.d.ts +28 -0
  138. package/dist/config/slugUtils.d.ts.map +1 -0
  139. package/dist/config/slugUtils.js +51 -0
  140. package/dist/config/slugUtils.js.map +1 -0
  141. package/dist/level0/ServiceDirectory.d.ts +6 -6
  142. package/dist/level0/ServiceDirectory.js +11 -11
  143. package/dist/level0/ServiceDirectory.js.map +1 -1
  144. package/dist/level1/Agent.d.ts +10 -10
  145. package/dist/level1/Agent.d.ts.map +1 -1
  146. package/dist/level1/Agent.js +45 -29
  147. package/dist/level1/Agent.js.map +1 -1
  148. package/dist/level1/pricing/PriceCalculator.js +2 -2
  149. package/dist/level1/pricing/PriceCalculator.js.map +1 -1
  150. package/dist/negotiation/BuyerOrchestrator.d.ts +108 -0
  151. package/dist/negotiation/BuyerOrchestrator.d.ts.map +1 -0
  152. package/dist/negotiation/BuyerOrchestrator.js +377 -0
  153. package/dist/negotiation/BuyerOrchestrator.js.map +1 -0
  154. package/dist/negotiation/DecisionEngine.d.ts +44 -0
  155. package/dist/negotiation/DecisionEngine.d.ts.map +1 -0
  156. package/dist/negotiation/DecisionEngine.js +116 -0
  157. package/dist/negotiation/DecisionEngine.js.map +1 -0
  158. package/dist/negotiation/PolicyEngine.d.ts +126 -0
  159. package/dist/negotiation/PolicyEngine.d.ts.map +1 -0
  160. package/dist/negotiation/PolicyEngine.js +265 -0
  161. package/dist/negotiation/PolicyEngine.js.map +1 -0
  162. package/dist/negotiation/SessionStore.d.ts +57 -0
  163. package/dist/negotiation/SessionStore.d.ts.map +1 -0
  164. package/dist/negotiation/SessionStore.js +179 -0
  165. package/dist/negotiation/SessionStore.js.map +1 -0
  166. package/dist/negotiation/index.d.ts +9 -0
  167. package/dist/negotiation/index.d.ts.map +1 -0
  168. package/dist/negotiation/index.js +12 -0
  169. package/dist/negotiation/index.js.map +1 -0
  170. package/dist/protocol/ACTPKernel.d.ts +32 -4
  171. package/dist/protocol/ACTPKernel.d.ts.map +1 -1
  172. package/dist/protocol/ACTPKernel.js +70 -16
  173. package/dist/protocol/ACTPKernel.js.map +1 -1
  174. package/dist/protocol/AgentRegistry.js +2 -2
  175. package/dist/protocol/AgentRegistry.js.map +1 -1
  176. package/dist/protocol/DIDResolver.js +2 -2
  177. package/dist/protocol/DIDResolver.js.map +1 -1
  178. package/dist/protocol/EASHelper.d.ts +2 -2
  179. package/dist/protocol/EASHelper.js +5 -5
  180. package/dist/protocol/EASHelper.js.map +1 -1
  181. package/dist/protocol/EscrowVault.d.ts +2 -2
  182. package/dist/protocol/EscrowVault.js +4 -4
  183. package/dist/protocol/EscrowVault.js.map +1 -1
  184. package/dist/protocol/EventMonitor.d.ts +4 -4
  185. package/dist/protocol/EventMonitor.js +5 -5
  186. package/dist/protocol/EventMonitor.js.map +1 -1
  187. package/dist/protocol/MessageSigner.d.ts +5 -5
  188. package/dist/protocol/MessageSigner.js +8 -8
  189. package/dist/protocol/MessageSigner.js.map +1 -1
  190. package/dist/protocol/ProofGenerator.d.ts +4 -4
  191. package/dist/protocol/ProofGenerator.js +6 -6
  192. package/dist/protocol/ProofGenerator.js.map +1 -1
  193. package/dist/runtime/BlockchainRuntime.d.ts +24 -14
  194. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
  195. package/dist/runtime/BlockchainRuntime.js +60 -45
  196. package/dist/runtime/BlockchainRuntime.js.map +1 -1
  197. package/dist/runtime/IACTPRuntime.d.ts +12 -1
  198. package/dist/runtime/IACTPRuntime.d.ts.map +1 -1
  199. package/dist/runtime/MockRuntime.d.ts +22 -9
  200. package/dist/runtime/MockRuntime.d.ts.map +1 -1
  201. package/dist/runtime/MockRuntime.js +76 -24
  202. package/dist/runtime/MockRuntime.js.map +1 -1
  203. package/dist/runtime/MockStateManager.js +2 -2
  204. package/dist/runtime/MockStateManager.js.map +1 -1
  205. package/dist/runtime/types/MockState.d.ts +1 -1
  206. package/dist/types/erc8004.d.ts +2 -2
  207. package/dist/types/erc8004.d.ts.map +1 -1
  208. package/dist/types/erc8004.js +4 -1
  209. package/dist/types/erc8004.js.map +1 -1
  210. package/dist/types/state.d.ts +1 -1
  211. package/dist/types/state.js +1 -1
  212. package/dist/types/transaction.d.ts +4 -0
  213. package/dist/types/transaction.d.ts.map +1 -1
  214. package/dist/utils/ErrorRecoveryGuide.d.ts +1 -1
  215. package/dist/utils/ErrorRecoveryGuide.js +1 -1
  216. package/dist/utils/Helpers.d.ts +6 -6
  217. package/dist/utils/Helpers.js +7 -7
  218. package/dist/utils/Helpers.js.map +1 -1
  219. package/dist/utils/IPFSClient.d.ts +7 -7
  220. package/dist/utils/IPFSClient.js +9 -9
  221. package/dist/utils/IPFSClient.js.map +1 -1
  222. package/dist/utils/Logger.d.ts +4 -4
  223. package/dist/utils/Logger.js +8 -8
  224. package/dist/utils/Logger.js.map +1 -1
  225. package/dist/utils/NonceManager.d.ts +9 -9
  226. package/dist/utils/NonceManager.js +19 -19
  227. package/dist/utils/NonceManager.js.map +1 -1
  228. package/dist/utils/RateLimiter.d.ts +10 -10
  229. package/dist/utils/RateLimiter.d.ts.map +1 -1
  230. package/dist/utils/RateLimiter.js +22 -22
  231. package/dist/utils/RateLimiter.js.map +1 -1
  232. package/dist/utils/ReceivedNonceTracker.d.ts +10 -10
  233. package/dist/utils/ReceivedNonceTracker.js +20 -20
  234. package/dist/utils/ReceivedNonceTracker.js.map +1 -1
  235. package/dist/utils/SDKLifecycle.d.ts +3 -3
  236. package/dist/utils/SDKLifecycle.js +7 -7
  237. package/dist/utils/SDKLifecycle.js.map +1 -1
  238. package/dist/utils/SecureNonce.d.ts +1 -1
  239. package/dist/utils/SecureNonce.js +1 -1
  240. package/dist/utils/Semaphore.d.ts +2 -2
  241. package/dist/utils/Semaphore.js +2 -2
  242. package/dist/utils/UsedAttestationTracker.d.ts +13 -13
  243. package/dist/utils/UsedAttestationTracker.js +20 -20
  244. package/dist/utils/UsedAttestationTracker.js.map +1 -1
  245. package/dist/utils/security.d.ts +3 -3
  246. package/dist/utils/security.js +4 -4
  247. package/dist/utils/security.js.map +1 -1
  248. package/dist/utils/validation.d.ts +4 -4
  249. package/dist/utils/validation.js +9 -9
  250. package/dist/utils/validation.js.map +1 -1
  251. package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
  252. package/dist/wallet/AutoWalletProvider.js +2 -1
  253. package/dist/wallet/AutoWalletProvider.js.map +1 -1
  254. package/dist/wallet/IWalletProvider.d.ts +2 -0
  255. package/dist/wallet/IWalletProvider.d.ts.map +1 -1
  256. package/dist/wallet/aa/TransactionBatcher.d.ts +22 -2
  257. package/dist/wallet/aa/TransactionBatcher.d.ts.map +1 -1
  258. package/dist/wallet/aa/TransactionBatcher.js +51 -9
  259. package/dist/wallet/aa/TransactionBatcher.js.map +1 -1
  260. package/package.json +6 -12
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ /**
3
+ * Negotiate Command — Autonomous buyer-side negotiation
4
+ *
5
+ * Discovers agents, scores them, validates against buyer policy,
6
+ * and optionally executes the full negotiation flow.
7
+ *
8
+ * @module cli/commands/negotiate
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || function (mod) {
27
+ if (mod && mod.__esModule) return mod;
28
+ var result = {};
29
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
30
+ __setModuleDefault(result, mod);
31
+ return result;
32
+ };
33
+ Object.defineProperty(exports, "__esModule", { value: true });
34
+ exports.createNegotiateCommand = void 0;
35
+ const commander_1 = require("commander");
36
+ const fs_1 = require("fs");
37
+ const output_1 = require("../utils/output");
38
+ const client_1 = require("../utils/client");
39
+ const BuyerOrchestrator_1 = require("../../negotiation/BuyerOrchestrator");
40
+ // ============================================================================
41
+ // Command Definition
42
+ // ============================================================================
43
+ function createNegotiateCommand() {
44
+ const cmd = new commander_1.Command('negotiate')
45
+ .description('Run autonomous buyer-side negotiation')
46
+ .requiredOption('--policy <path>', 'Path to buyer policy JSON file')
47
+ .option('--dry-run', 'Score candidates without creating transactions')
48
+ .option('--poll-interval <ms>', 'Poll interval for quote state (ms)', '3000')
49
+ .option('--json', 'Output as JSON')
50
+ .option('-q, --quiet', 'Minimal output')
51
+ .action(async (options) => {
52
+ const output = new output_1.Output(options.json ? 'json' : options.quiet ? 'quiet' : 'human');
53
+ try {
54
+ await runNegotiate(options, output);
55
+ }
56
+ catch (error) {
57
+ const structuredError = (0, client_1.mapError)(error);
58
+ output.errorResult({
59
+ code: structuredError.code,
60
+ message: structuredError.message,
61
+ details: structuredError.details,
62
+ });
63
+ process.exit(output_1.ExitCode.ERROR);
64
+ }
65
+ });
66
+ return cmd;
67
+ }
68
+ exports.createNegotiateCommand = createNegotiateCommand;
69
+ // ============================================================================
70
+ // Implementation
71
+ // ============================================================================
72
+ async function runNegotiate(options, output) {
73
+ // Load policy
74
+ let policy;
75
+ try {
76
+ const raw = (0, fs_1.readFileSync)(options.policy, 'utf8');
77
+ policy = JSON.parse(raw);
78
+ }
79
+ catch (err) {
80
+ output.errorResult({
81
+ code: 'INVALID_POLICY',
82
+ message: `Failed to load policy: ${err instanceof Error ? err.message : String(err)}`,
83
+ });
84
+ process.exit(output_1.ExitCode.ERROR);
85
+ }
86
+ // Validate required policy fields (structure + types + ranges)
87
+ const errors = [];
88
+ if (!policy.task || typeof policy.task !== 'string') {
89
+ errors.push('task must be a non-empty string');
90
+ }
91
+ if (typeof policy.constraints?.max_unit_price?.amount !== 'number' || !Number.isFinite(policy.constraints.max_unit_price.amount) || policy.constraints.max_unit_price.amount <= 0) {
92
+ errors.push('constraints.max_unit_price.amount must be a finite positive number');
93
+ }
94
+ if (typeof policy.constraints?.max_daily_spend?.amount !== 'number' || !Number.isFinite(policy.constraints.max_daily_spend.amount) || policy.constraints.max_daily_spend.amount <= 0) {
95
+ errors.push('constraints.max_daily_spend.amount must be a finite positive number');
96
+ }
97
+ if (typeof policy.negotiation?.rounds_max !== 'number' || !Number.isInteger(policy.negotiation.rounds_max) || policy.negotiation.rounds_max < 1) {
98
+ errors.push('negotiation.rounds_max must be a positive integer');
99
+ }
100
+ if (!policy.negotiation?.quote_ttl || typeof policy.negotiation.quote_ttl !== 'string') {
101
+ errors.push('negotiation.quote_ttl must be a string (e.g. "15m", "2h")');
102
+ }
103
+ else {
104
+ // Validate TTL format early (before orchestrator)
105
+ try {
106
+ const { PolicyEngine } = await Promise.resolve().then(() => __importStar(require('../../negotiation/PolicyEngine')));
107
+ PolicyEngine.parseTtl(policy.negotiation.quote_ttl);
108
+ }
109
+ catch {
110
+ errors.push(`negotiation.quote_ttl has invalid format: "${policy.negotiation.quote_ttl}" (expected e.g. "15m", "2h", "30s")`);
111
+ }
112
+ }
113
+ if (!Array.isArray(policy.selection?.prioritize) || policy.selection.prioritize.length === 0) {
114
+ errors.push('selection.prioritize must be a non-empty array');
115
+ }
116
+ if (errors.length > 0) {
117
+ output.errorResult({
118
+ code: 'INVALID_POLICY',
119
+ message: `Invalid policy: ${errors.join('; ')}`,
120
+ });
121
+ process.exit(output_1.ExitCode.ERROR);
122
+ }
123
+ const rawPollInterval = options.pollInterval ?? '3000';
124
+ const pollInterval = /^\d+$/.test(rawPollInterval) ? Number(rawPollInterval) : NaN;
125
+ if (isNaN(pollInterval) || pollInterval < 100) {
126
+ output.errorResult({
127
+ code: 'INVALID_OPTION',
128
+ message: `--poll-interval must be a whole number >= 100ms, got: "${rawPollInterval}"`,
129
+ });
130
+ process.exit(output_1.ExitCode.ERROR);
131
+ }
132
+ const spinner = output.spinner(options.dryRun ? 'Scoring candidates...' : 'Negotiating...');
133
+ const client = await (0, client_1.createClient)();
134
+ const orchestrator = new BuyerOrchestrator_1.BuyerOrchestrator(policy, client.runtime, client.getAddress());
135
+ // Progress callback for human mode
136
+ const onProgress = (event) => {
137
+ if (options.json || options.quiet)
138
+ return;
139
+ switch (event.type) {
140
+ case 'discovery':
141
+ spinner.stop(true);
142
+ output.print(`Found ${event.candidates} candidates`);
143
+ break;
144
+ case 'scoring':
145
+ output.print(`Ranked ${event.ranked} candidates`);
146
+ break;
147
+ case 'round_start':
148
+ output.print(`Round ${event.round}: trying ${output_1.fmt.cyan(event.provider)}...`);
149
+ break;
150
+ case 'waiting_quote':
151
+ output.print(` Waiting for quote (${event.ttlSeconds}s TTL)...`);
152
+ break;
153
+ case 'quote_received':
154
+ output.print(' Quote received, validating...');
155
+ break;
156
+ case 'round_end':
157
+ if (event.action === 'accepted') {
158
+ output.success(`Round ${event.round}: ${output_1.fmt.green('accepted')} — ${event.reason}`);
159
+ }
160
+ else {
161
+ output.print(` Round ${event.round}: ${output_1.fmt.dim(event.action)} — ${event.reason}`);
162
+ }
163
+ break;
164
+ case 'complete':
165
+ break;
166
+ }
167
+ };
168
+ try {
169
+ const result = await orchestrator.negotiate({
170
+ dryRun: options.dryRun,
171
+ pollIntervalMs: pollInterval,
172
+ onProgress,
173
+ });
174
+ spinner.stop(result.success);
175
+ // Output result
176
+ output.result({
177
+ success: result.success,
178
+ commerce_session_id: result.commerce_session_id,
179
+ actp_tx_id: result.actp_tx_id,
180
+ selected_provider: result.selected_provider,
181
+ rounds_used: result.rounds_used,
182
+ reason: result.reason,
183
+ rounds: result.rounds,
184
+ }, { quietKey: result.success ? 'actp_tx_id' : 'reason' });
185
+ process.exit(result.success ? output_1.ExitCode.SUCCESS : output_1.ExitCode.ERROR);
186
+ }
187
+ catch (err) {
188
+ spinner.stop(false);
189
+ throw err;
190
+ }
191
+ }
192
+ //# sourceMappingURL=negotiate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"negotiate.js","sourceRoot":"","sources":["../../../src/cli/commands/negotiate.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/publish.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsEpC,wBAAgB,oBAAoB,IAAI,OAAO,CA4B9C"}
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/publish.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyEpC,wBAAgB,oBAAoB,IAAI,OAAO,CA4B9C"}
@@ -49,9 +49,12 @@ const agirailsmd_1 = require("../../config/agirailsmd");
49
49
  const publishPipeline_1 = require("../../config/publishPipeline");
50
50
  const pendingPublish_1 = require("../../config/pendingPublish");
51
51
  const config_1 = require("../utils/config");
52
+ const ethers_1 = require("ethers");
52
53
  const FilebaseClient_1 = require("../../storage/FilebaseClient");
53
54
  const ArweaveClient_1 = require("../../storage/ArweaveClient");
54
55
  const wallet_1 = require("../utils/wallet");
56
+ const agirailsmdV4_1 = require("../../config/agirailsmdV4");
57
+ const agirailsApp_1 = require("../../api/agirailsApp");
55
58
  // ============================================================================
56
59
  // Publish Proxy (fallback when no Filebase credentials)
57
60
  // ============================================================================
@@ -101,7 +104,7 @@ async function publishViaProxy(content, localConfigHash) {
101
104
  function createPublishCommand() {
102
105
  const cmd = new commander_1.Command('publish')
103
106
  .description('Publish AGIRAILS.md config (offline — activates on first payment)')
104
- .argument('[path]', 'Path to AGIRAILS.md', './AGIRAILS.md')
107
+ .argument('[path]', 'Path to AGIRAILS.md or {slug}.md')
105
108
  .option('-n, --network <network>', 'DEPRECATED: network is auto-detected (accepted but ignored)')
106
109
  .option('--skip-arweave', 'Skip permanent Arweave storage (dev mode)')
107
110
  .option('--dry-run', 'Show what would happen without executing')
@@ -130,16 +133,33 @@ async function runPublish(filePath, options, output) {
130
133
  if (options.network) {
131
134
  output.warning('--network flag is deprecated and ignored. Network is auto-detected at payment time.');
132
135
  }
133
- const resolvedPath = (0, path_1.resolve)(filePath);
136
+ // Resolve file path: explicit arg > identity pointer > ./AGIRAILS.md fallback
137
+ let effectivePath = filePath;
138
+ if (!effectivePath) {
139
+ const { resolveIdentityPath } = await Promise.resolve().then(() => __importStar(require('../utils/config')));
140
+ const identityPath = resolveIdentityPath();
141
+ if (identityPath) {
142
+ effectivePath = identityPath;
143
+ }
144
+ else if ((0, fs_1.existsSync)((0, path_1.resolve)('./AGIRAILS.md'))) {
145
+ effectivePath = './AGIRAILS.md';
146
+ }
147
+ else {
148
+ output.error('No file to publish. Provide a path, or create a {slug}.md identity file.\n' +
149
+ 'Usage: actp publish [path]');
150
+ process.exit(output_1.ExitCode.INVALID_INPUT);
151
+ }
152
+ }
153
+ let resolvedPath = (0, path_1.resolve)(effectivePath);
134
154
  if (!(0, fs_1.existsSync)(resolvedPath)) {
135
- output.error(`File not found: ${filePath}`);
155
+ output.error(`File not found: ${effectivePath}`);
136
156
  process.exit(output_1.ExitCode.INVALID_INPUT);
137
157
  }
138
158
  const spinner = output.spinner('Reading AGIRAILS.md...');
139
159
  try {
140
160
  // Read and compute hash
141
- const content = (0, fs_1.readFileSync)(resolvedPath, 'utf-8');
142
- const { configHash, structuredHash, bodyHash } = (0, agirailsmd_1.computeConfigHash)(content);
161
+ let content = (0, fs_1.readFileSync)(resolvedPath, 'utf-8');
162
+ let { configHash, structuredHash, bodyHash } = (0, agirailsmd_1.computeConfigHash)(content);
143
163
  if (options.dryRun) {
144
164
  spinner.stop(true);
145
165
  output.result({
@@ -153,6 +173,79 @@ async function runPublish(filePath, options, output) {
153
173
  output.success('Dry run complete. No changes made.');
154
174
  return;
155
175
  }
176
+ // ================================================================
177
+ // Phase 1: Slug check (pre-chain, no auth, only on first publish)
178
+ // ================================================================
179
+ let v4Config;
180
+ try {
181
+ v4Config = (0, agirailsmdV4_1.parseAgirailsMdV4)(content);
182
+ }
183
+ catch {
184
+ // Not a v4 file — skip slug check (backward compatible with v3 AGIRAILS.md)
185
+ }
186
+ if (v4Config && !v4Config.agent_id) {
187
+ // First publish — check slug availability
188
+ const slugSpinner = output.spinner(`Checking slug availability: ${v4Config.slug}...`);
189
+ try {
190
+ const slugResult = await (0, agirailsApp_1.checkSlug)(v4Config.slug);
191
+ if (!slugResult.available) {
192
+ if (slugResult.suggestion) {
193
+ slugSpinner.stop(true);
194
+ const oldSlug = v4Config.slug;
195
+ const newSlug = slugResult.suggestion;
196
+ // Auto-rename: update frontmatter slug, rename file, update config pointer
197
+ output.info(`Slug "${oldSlug}" was taken. Renamed to "${newSlug}".`);
198
+ // Rename file on disk
199
+ const { dirname, join: pathJoin } = await Promise.resolve().then(() => __importStar(require('path')));
200
+ const dir = dirname(resolvedPath);
201
+ const newPath = pathJoin(dir, `${newSlug}.md`);
202
+ (0, fs_1.renameSync)(resolvedPath, newPath);
203
+ // Re-read, update slug in frontmatter, rewrite, re-parse, recompute hash
204
+ const rawContent = (0, fs_1.readFileSync)(newPath, 'utf-8');
205
+ const parsed = (0, agirailsmd_1.parseAgirailsMd)(rawContent);
206
+ const updatedFm = { ...parsed.frontmatter, slug: newSlug };
207
+ const newContent = (0, agirailsmd_1.serializeAgirailsMd)(updatedFm, parsed.body);
208
+ (0, fs_1.writeFileSync)(newPath, newContent, 'utf-8');
209
+ // Update in-memory references for the rest of publish
210
+ resolvedPath = newPath;
211
+ v4Config.slug = newSlug;
212
+ // Recompute configHash with new slug
213
+ const reHash = (0, agirailsmd_1.computeConfigHash)(newContent);
214
+ configHash = reHash.configHash;
215
+ content = newContent;
216
+ // Update config.json identity pointer
217
+ try {
218
+ const config = (0, config_1.loadConfig)((0, path_1.resolve)(newPath, '..'));
219
+ config.identity = `${newSlug}.md`;
220
+ (0, config_1.saveConfig)(config, (0, path_1.resolve)(newPath, '..'));
221
+ }
222
+ catch {
223
+ // Best-effort
224
+ }
225
+ }
226
+ else {
227
+ slugSpinner.stop(false);
228
+ throw new Error(`Slug "${v4Config.slug}" is already taken on agirails.app. Choose a different name.`);
229
+ }
230
+ }
231
+ else {
232
+ slugSpinner.stop(true);
233
+ output.success(`Slug "${v4Config.slug}" is available.`);
234
+ }
235
+ }
236
+ catch (slugErr) {
237
+ if (slugErr.message.includes('already taken'))
238
+ throw slugErr;
239
+ if (slugErr.message.includes('was taken')) {
240
+ // Auto-rename succeeded — not an error
241
+ }
242
+ else {
243
+ slugSpinner.stop(false);
244
+ // Non-fatal: slug check API failure doesn't block publish
245
+ output.warning(`Slug check failed: ${slugErr.message}. Proceeding.`);
246
+ }
247
+ }
248
+ }
156
249
  // Ensure .actp directory exists
157
250
  const actpDir = (0, pendingPublish_1.getActpDir)();
158
251
  if (!(0, fs_1.existsSync)(actpDir)) {
@@ -231,7 +324,7 @@ async function runPublish(filePath, options, output) {
231
324
  serviceDescriptors: regParams.serviceDescriptors,
232
325
  createdAt: new Date().toISOString(),
233
326
  };
234
- const projectRoot = (0, path_1.resolve)(filePath, '..');
327
+ const projectRoot = (0, path_1.resolve)(resolvedPath, '..');
235
328
  // ================================================================
236
329
  // Local setup: bootstrap or migrate config, ensure .gitignore
237
330
  // "publish covers setup" — no separate `actp init` required.
@@ -263,11 +356,14 @@ async function runPublish(filePath, options, output) {
263
356
  // ALWAYS activate on testnet (one command, both networks per SPEC)
264
357
  // ================================================================
265
358
  let testnetTxHash;
359
+ let smartWalletAddress;
266
360
  const activationSpinner = output.spinner('Activating on testnet...');
267
361
  try {
268
- testnetTxHash = await activateOnTestnet(projectRoot, configHash, cid, regParams.endpoint, regParams.serviceDescriptors, output);
362
+ const activationResult = await activateOnTestnet(projectRoot, configHash, cid, regParams.endpoint, regParams.serviceDescriptors, output);
269
363
  activationSpinner.stop(true);
270
- if (testnetTxHash) {
364
+ if (activationResult) {
365
+ testnetTxHash = activationResult.txHash;
366
+ smartWalletAddress = activationResult.smartWalletAddress;
271
367
  output.success(`Testnet activation: ${testnetTxHash}`);
272
368
  }
273
369
  else {
@@ -283,6 +379,172 @@ async function runPublish(filePath, options, output) {
283
379
  }
284
380
  // Always save mainnet pending (lazy — activates on first mainnet payment)
285
381
  (0, pendingPublish_1.savePendingPublish)({ ...pendingData, network: 'base-mainnet' });
382
+ // ================================================================
383
+ // Write-back: wallet, agent_id, did into AGIRAILS.md frontmatter
384
+ // These are in PUBLISH_METADATA_KEYS — stripped before hash computation.
385
+ // ================================================================
386
+ const publishMetadata = {};
387
+ // Wallet write-back: Smart Wallet is the on-chain identity (NFT owner,
388
+ // escrow party). EOA is only a fallback for non-Smart-Wallet flows.
389
+ const existingWallet = frontmatter.wallet;
390
+ const canonicalWallet = smartWalletAddress || existingWallet || walletAddress;
391
+ if (canonicalWallet) {
392
+ publishMetadata.wallet = canonicalWallet;
393
+ publishMetadata.did = `did:ethr:84532:${canonicalWallet}`;
394
+ }
395
+ // agent_id: query ERC-8004 Identity Registry for minted tokenId
396
+ // Use Smart Wallet address (NFT owner) when available, fall back to EOA
397
+ const ownerAddress = smartWalletAddress || existingWallet || walletAddress;
398
+ if (testnetTxHash && ownerAddress) {
399
+ try {
400
+ const { getNetwork: getNet } = await Promise.resolve().then(() => __importStar(require('../../config/networks')));
401
+ const { ethers: eth } = await Promise.resolve().then(() => __importStar(require('ethers')));
402
+ const net = getNet('base-sepolia');
403
+ const prov = new eth.JsonRpcProvider(net.rpcUrl);
404
+ // Query ERC-8004 Identity Registry for the agent's NFT tokenId
405
+ const erc8004Addr = net.contracts.erc8004IdentityRegistry;
406
+ if (erc8004Addr) {
407
+ const { ERC8004_IDENTITY_ABI } = await Promise.resolve().then(() => __importStar(require('../../types/erc8004')));
408
+ const erc8004 = new eth.Contract(erc8004Addr, ERC8004_IDENTITY_ABI, prov);
409
+ // Parse Registered event from tx receipt for exact agentId
410
+ let agentId;
411
+ try {
412
+ const receipt = await prov.getTransactionReceipt(testnetTxHash);
413
+ if (receipt) {
414
+ const registeredTopic = eth.id('Registered(uint256,string,address)');
415
+ for (const log of receipt.logs) {
416
+ if (log.address.toLowerCase() === erc8004Addr.toLowerCase()
417
+ && log.topics[0] === registeredTopic) {
418
+ // agentId is the first indexed parameter
419
+ agentId = BigInt(log.topics[1]).toString();
420
+ break;
421
+ }
422
+ }
423
+ }
424
+ }
425
+ catch {
426
+ // Event parsing failed — fall back to balanceOf query
427
+ }
428
+ // Fallback: query by balance if event parsing didn't work
429
+ if (!agentId) {
430
+ const balance = await erc8004.balanceOf(ownerAddress);
431
+ if (Number(balance) > 0) {
432
+ const lastIndex = Number(balance) - 1;
433
+ agentId = (await erc8004.tokenOfOwnerByIndex(ownerAddress, lastIndex)).toString();
434
+ }
435
+ }
436
+ if (agentId) {
437
+ publishMetadata.agent_id = agentId;
438
+ publishMetadata.did = `did:ethr:84532:${ownerAddress}`;
439
+ }
440
+ }
441
+ // Fallback: check AgentRegistry if ERC-8004 didn't yield an agent_id
442
+ if (!publishMetadata.agent_id) {
443
+ const registryAddr = net.contracts.agentRegistry;
444
+ if (registryAddr) {
445
+ const { AgentRegistryClient: ARC } = await Promise.resolve().then(() => __importStar(require('../../registry/AgentRegistryClient')));
446
+ const regClient = ARC.readOnly(registryAddr, prov);
447
+ const onChainConfig = await regClient.getConfig(ownerAddress);
448
+ if (onChainConfig.isActive) {
449
+ const agentId = BigInt(ownerAddress).toString();
450
+ publishMetadata.agent_id = agentId;
451
+ publishMetadata.did = `did:ethr:84532:${ownerAddress}`;
452
+ }
453
+ }
454
+ }
455
+ }
456
+ catch {
457
+ // Best-effort — agent_id will be written on re-publish
458
+ }
459
+ }
460
+ // ================================================================
461
+ // Phase 1: API upsert to agirails.app (post-chain, non-blocking)
462
+ // Requires agent_id — skipped on first publish (agent_id assigned
463
+ // on-chain, written back to YAML, available on re-publish).
464
+ // API routes: POST /api/v1/agents (dual auth: session + wallet-sig)
465
+ // ================================================================
466
+ if (v4Config && v4Config.agent_id && walletAddress) {
467
+ const apiSpinner = output.spinner('Syncing with agirails.app...');
468
+ try {
469
+ const publishTimestamp = Math.floor(Date.now() / 1000);
470
+ // C-2 fix: include network in signed message to prevent cross-network replay
471
+ // Upsert only fires after testnet activation, so network is always base-sepolia
472
+ const publishNetwork = 'base-sepolia';
473
+ const upsertMessage = `agirails-publish:${v4Config.slug}:${configHash}:${publishNetwork}:${publishTimestamp}`;
474
+ const { resolvePrivateKey: resolveKey } = await Promise.resolve().then(() => __importStar(require('../../wallet/keystore')));
475
+ const privKey = await resolveKey(projectRoot, { network: 'testnet' });
476
+ if (privKey) {
477
+ const signer = new ethers_1.ethers.Wallet(privKey);
478
+ const sig = await signer.signMessage(upsertMessage);
479
+ const apiResult = await (0, agirailsApp_1.upsertAgent)({
480
+ slug: v4Config.slug,
481
+ agentId: v4Config.agent_id,
482
+ wallet: smartWalletAddress || existingWallet || walletAddress,
483
+ signer: walletAddress, // EOA that signed the message
484
+ configCid: cid,
485
+ configHash,
486
+ signature: sig,
487
+ message: upsertMessage,
488
+ timestamp: publishTimestamp,
489
+ network: publishNetwork,
490
+ config: {
491
+ name: v4Config.name,
492
+ description: (v4Config.description || "").replace(/^#\s+[^\n]+\n*/, "").trim(),
493
+ capabilities: v4Config.services,
494
+ pricing: {
495
+ model: "fixed",
496
+ amount: String(v4Config.pricing.base),
497
+ unit: v4Config.pricing.unit || "job",
498
+ currency: v4Config.pricing.currency || "USDC",
499
+ minimum: String(v4Config.pricing.min_price ?? v4Config.pricing.base),
500
+ },
501
+ sla: {
502
+ availability: "24/7",
503
+ responseTime: { p50: 30, p95: 300 },
504
+ ...(v4Config.sla.concurrency ? { throughput: v4Config.sla.concurrency + " concurrent" } : {}),
505
+ },
506
+ ...(v4Config.sla.concurrency ? { concurrency: v4Config.sla.concurrency } : {}),
507
+ payment_mode: v4Config.payment.modes.includes("x402") ? "x402" : "actp",
508
+ network: v4Config.network,
509
+ // Covenant: map V4 accepts/returns to web input/output format
510
+ ...(v4Config.covenant.accepts && Object.keys(v4Config.covenant.accepts).length > 0 ? {
511
+ covenant: {
512
+ input: Object.entries(v4Config.covenant.accepts).map(([k, v]) => k + ": " + v).join("\n"),
513
+ output: Object.entries(v4Config.covenant.returns).map(([k, v]) => k + ": " + v).join("\n"),
514
+ guarantees: [],
515
+ dispute: { window_hours: 24, resolution: "auto-refund" },
516
+ },
517
+ } : {}),
518
+ // Endpoint: for x402 agents
519
+ ...(v4Config.endpoint ? {
520
+ endpoints: { execute: v4Config.endpoint },
521
+ } : {}),
522
+ },
523
+ });
524
+ apiSpinner.stop(true);
525
+ output.success(`Profile live at: agirails.app/a/${v4Config.slug}`);
526
+ // Display claim code if returned (for linking to dashboard)
527
+ if (apiResult.claimCode) {
528
+ output.print(` Claim code: ${apiResult.claimCode}`);
529
+ output.print(` Claim link: https://agirails.app/claim?code=${apiResult.claimCode}`);
530
+ output.print(' (use this to link the agent to your dashboard account)');
531
+ }
532
+ }
533
+ else {
534
+ apiSpinner.stop(false);
535
+ output.info('Skipped agirails.app sync (no wallet key for signing).');
536
+ }
537
+ }
538
+ catch (apiErr) {
539
+ apiSpinner.stop(false);
540
+ // Non-blocking — agent is already on-chain
541
+ output.warning(`agirails.app sync failed: ${apiErr.message}`);
542
+ output.print(' Agent is on-chain. Retry with: actp publish');
543
+ }
544
+ }
545
+ else if (v4Config && !v4Config.agent_id) {
546
+ output.info('First publish — agirails.app sync will happen on re-publish (after agent_id is assigned).');
547
+ }
286
548
  // Update AGIRAILS.md frontmatter
287
549
  const updatedFrontmatter = {
288
550
  ...frontmatter,
@@ -290,9 +552,25 @@ async function runPublish(filePath, options, output) {
290
552
  config_cid: cid,
291
553
  published_at: new Date().toISOString(),
292
554
  ...(arweaveTxId ? { arweave_tx: arweaveTxId } : {}),
555
+ ...publishMetadata,
293
556
  };
294
557
  const updatedContent = (0, agirailsmd_1.serializeAgirailsMd)(updatedFrontmatter, body);
295
558
  (0, fs_1.writeFileSync)(resolvedPath, updatedContent, 'utf-8');
559
+ // Update identity pointer in config.json if this is a {slug}.md file
560
+ if (v4Config) {
561
+ try {
562
+ const { basename } = await Promise.resolve().then(() => __importStar(require('path')));
563
+ const config = (0, config_1.loadConfig)(projectRoot);
564
+ const filename = basename(resolvedPath);
565
+ if (config.identity !== filename) {
566
+ config.identity = filename;
567
+ (0, config_1.saveConfig)(config, projectRoot);
568
+ }
569
+ }
570
+ catch {
571
+ // Best-effort — config might not exist yet
572
+ }
573
+ }
296
574
  // Output results
297
575
  output.result({
298
576
  configHash,
@@ -310,17 +588,31 @@ async function runPublish(filePath, options, output) {
310
588
  }
311
589
  output.print('');
312
590
  output.print('Mainnet: on-chain activation will happen on your first payment.');
591
+ // Context-aware next steps
592
+ const hasEndpoint = frontmatter.endpoint && frontmatter.endpoint !== publishPipeline_1.PENDING_ENDPOINT;
313
593
  output.print('');
314
594
  output.print('Next steps:');
315
- output.print(' - Verify config: actp diff');
316
- output.print(' - Make a payment: your first mainnet payment activates the agent on-chain');
595
+ if (!hasEndpoint) {
596
+ output.print(' 1. Set your endpoint: Add "endpoint: https://..." to AGIRAILS.md');
597
+ output.print(' 2. Check endpoint: actp health');
598
+ output.print(' 3. Check your balance: actp balance');
599
+ output.print(' 4. Verify config match: actp diff');
600
+ }
601
+ else {
602
+ output.print(' 1. Check endpoint: actp health');
603
+ output.print(' 2. Check your balance: actp balance');
604
+ output.print(' 3. Verify config match: actp diff');
605
+ }
606
+ // Suggest test payment on testnet
607
+ if (testnetTxHash && v4Config?.slug) {
608
+ output.print('');
609
+ output.print(` Try a test payment: actp pay agirails.app/a/${v4Config.slug} 5`);
610
+ }
317
611
  // Warn if placeholder endpoint
318
- if (!frontmatter.endpoint || frontmatter.endpoint === publishPipeline_1.PENDING_ENDPOINT) {
612
+ if (!hasEndpoint) {
319
613
  output.print('');
320
- output.warning('No endpoint in AGIRAILS.md using placeholder URL.');
321
- output.print(' Update when your agent is deployed:');
322
- output.print(' 1. Add "endpoint: https://your-agent.com/webhook" to AGIRAILS.md');
323
- output.print(' 2. Run: actp publish');
614
+ output.warning('No endpoint setyour agent can\'t receive jobs yet.');
615
+ output.print(' Add "endpoint: https://your-agent.com/webhook" to AGIRAILS.md, then: actp publish');
324
616
  }
325
617
  }
326
618
  catch (error) {
@@ -393,7 +685,7 @@ async function activateOnTestnet(projectRoot, configHash, cid, endpoint, service
393
685
  // Already up-to-date on-chain — no activation needed
394
686
  return undefined;
395
687
  }
396
- // Build activation calls
688
+ // Build activation calls (includes ERC-8004 identity mint for scenario A)
397
689
  const activationCalls = buildActivationBatch({
398
690
  scenario,
399
691
  agentRegistryAddress: networkConfig.contracts.agentRegistry,
@@ -401,6 +693,7 @@ async function activateOnTestnet(projectRoot, configHash, cid, endpoint, service
401
693
  configHash,
402
694
  listed: true,
403
695
  ...(scenario === 'A' ? { endpoint, serviceDescriptors } : {}),
696
+ erc8004IdentityRegistry: networkConfig.contracts.erc8004IdentityRegistry,
404
697
  });
405
698
  // Always mint test USDC on testnet (SPEC: "always")
406
699
  const mintCalls = buildTestnetMintBatch(networkConfig.contracts.usdc, smartWalletAddress, '1000000000');
@@ -416,6 +709,6 @@ async function activateOnTestnet(projectRoot, configHash, cid, endpoint, service
416
709
  throw new Error(`Testnet activation UserOp failed: ${receipt.hash}`);
417
710
  }
418
711
  output.success('Minted 1,000 test USDC to Smart Wallet');
419
- return receipt.hash;
712
+ return { txHash: receipt.hash, smartWalletAddress };
420
713
  }
421
714
  //# sourceMappingURL=publish.js.map