@agirails/sdk 2.7.0 → 3.1.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 (264) hide show
  1. package/README.md +1 -1
  2. package/bin/agirails +10 -0
  3. package/dist/ACTPClient.d.ts +15 -4
  4. package/dist/ACTPClient.d.ts.map +1 -1
  5. package/dist/ACTPClient.js +20 -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 +313 -18
  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 +260 -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 +36 -14
  194. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
  195. package/dist/runtime/BlockchainRuntime.js +78 -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 +29 -9
  200. package/dist/runtime/MockRuntime.d.ts.map +1 -1
  201. package/dist/runtime/MockRuntime.js +88 -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/settle/SettleOnInteract.d.ts +32 -0
  207. package/dist/settle/SettleOnInteract.d.ts.map +1 -0
  208. package/dist/settle/SettleOnInteract.js +74 -0
  209. package/dist/settle/SettleOnInteract.js.map +1 -0
  210. package/dist/types/erc8004.d.ts +2 -2
  211. package/dist/types/erc8004.d.ts.map +1 -1
  212. package/dist/types/erc8004.js +4 -1
  213. package/dist/types/erc8004.js.map +1 -1
  214. package/dist/types/state.d.ts +1 -1
  215. package/dist/types/state.js +1 -1
  216. package/dist/types/transaction.d.ts +4 -0
  217. package/dist/types/transaction.d.ts.map +1 -1
  218. package/dist/utils/ErrorRecoveryGuide.d.ts +1 -1
  219. package/dist/utils/ErrorRecoveryGuide.js +1 -1
  220. package/dist/utils/Helpers.d.ts +6 -6
  221. package/dist/utils/Helpers.js +7 -7
  222. package/dist/utils/Helpers.js.map +1 -1
  223. package/dist/utils/IPFSClient.d.ts +7 -7
  224. package/dist/utils/IPFSClient.js +9 -9
  225. package/dist/utils/IPFSClient.js.map +1 -1
  226. package/dist/utils/Logger.d.ts +4 -4
  227. package/dist/utils/Logger.js +8 -8
  228. package/dist/utils/Logger.js.map +1 -1
  229. package/dist/utils/NonceManager.d.ts +9 -9
  230. package/dist/utils/NonceManager.js +19 -19
  231. package/dist/utils/NonceManager.js.map +1 -1
  232. package/dist/utils/RateLimiter.d.ts +10 -10
  233. package/dist/utils/RateLimiter.d.ts.map +1 -1
  234. package/dist/utils/RateLimiter.js +22 -22
  235. package/dist/utils/RateLimiter.js.map +1 -1
  236. package/dist/utils/ReceivedNonceTracker.d.ts +10 -10
  237. package/dist/utils/ReceivedNonceTracker.js +20 -20
  238. package/dist/utils/ReceivedNonceTracker.js.map +1 -1
  239. package/dist/utils/SDKLifecycle.d.ts +3 -3
  240. package/dist/utils/SDKLifecycle.js +7 -7
  241. package/dist/utils/SDKLifecycle.js.map +1 -1
  242. package/dist/utils/SecureNonce.d.ts +1 -1
  243. package/dist/utils/SecureNonce.js +1 -1
  244. package/dist/utils/Semaphore.d.ts +2 -2
  245. package/dist/utils/Semaphore.js +2 -2
  246. package/dist/utils/UsedAttestationTracker.d.ts +13 -13
  247. package/dist/utils/UsedAttestationTracker.js +20 -20
  248. package/dist/utils/UsedAttestationTracker.js.map +1 -1
  249. package/dist/utils/security.d.ts +3 -3
  250. package/dist/utils/security.js +4 -4
  251. package/dist/utils/security.js.map +1 -1
  252. package/dist/utils/validation.d.ts +4 -4
  253. package/dist/utils/validation.js +9 -9
  254. package/dist/utils/validation.js.map +1 -1
  255. package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
  256. package/dist/wallet/AutoWalletProvider.js +2 -1
  257. package/dist/wallet/AutoWalletProvider.js.map +1 -1
  258. package/dist/wallet/IWalletProvider.d.ts +2 -0
  259. package/dist/wallet/IWalletProvider.d.ts.map +1 -1
  260. package/dist/wallet/aa/TransactionBatcher.d.ts +22 -2
  261. package/dist/wallet/aa/TransactionBatcher.d.ts.map +1 -1
  262. package/dist/wallet/aa/TransactionBatcher.js +51 -9
  263. package/dist/wallet/aa/TransactionBatcher.js.map +1 -1
  264. 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 {
@@ -281,8 +377,176 @@ async function runPublish(filePath, options, output) {
281
377
  output.warning(`Testnet activation failed: ${activationError.message}\n` +
282
378
  ' Saved as pending — will activate on first testnet payment.');
283
379
  }
284
- // Always save mainnet pending (lazy — activates on first mainnet payment)
380
+ // Save mainnet pending (lazy — activates on first mainnet payment).
381
+ // This is intentional even when config mode is testnet: the agent may later
382
+ // switch to mainnet, and the pending file ensures activation happens automatically.
285
383
  (0, pendingPublish_1.savePendingPublish)({ ...pendingData, network: 'base-mainnet' });
384
+ // ================================================================
385
+ // Write-back: wallet, agent_id, did into AGIRAILS.md frontmatter
386
+ // These are in PUBLISH_METADATA_KEYS — stripped before hash computation.
387
+ // ================================================================
388
+ const publishMetadata = {};
389
+ // Wallet write-back: Smart Wallet is the on-chain identity (NFT owner,
390
+ // escrow party). EOA is only a fallback for non-Smart-Wallet flows.
391
+ const existingWallet = frontmatter.wallet;
392
+ const canonicalWallet = smartWalletAddress || existingWallet || walletAddress;
393
+ if (canonicalWallet) {
394
+ publishMetadata.wallet = canonicalWallet;
395
+ publishMetadata.did = `did:ethr:84532:${canonicalWallet}`;
396
+ }
397
+ // agent_id: query ERC-8004 Identity Registry for minted tokenId
398
+ // Use Smart Wallet address (NFT owner) when available, fall back to EOA
399
+ const ownerAddress = smartWalletAddress || existingWallet || walletAddress;
400
+ if (testnetTxHash && ownerAddress) {
401
+ try {
402
+ const { getNetwork: getNet } = await Promise.resolve().then(() => __importStar(require('../../config/networks')));
403
+ const { ethers: eth } = await Promise.resolve().then(() => __importStar(require('ethers')));
404
+ const net = getNet('base-sepolia');
405
+ const prov = new eth.JsonRpcProvider(net.rpcUrl);
406
+ // Query ERC-8004 Identity Registry for the agent's NFT tokenId
407
+ const erc8004Addr = net.contracts.erc8004IdentityRegistry;
408
+ if (erc8004Addr) {
409
+ const { ERC8004_IDENTITY_ABI } = await Promise.resolve().then(() => __importStar(require('../../types/erc8004')));
410
+ const erc8004 = new eth.Contract(erc8004Addr, ERC8004_IDENTITY_ABI, prov);
411
+ // Parse Registered event from tx receipt for exact agentId
412
+ let agentId;
413
+ try {
414
+ const receipt = await prov.getTransactionReceipt(testnetTxHash);
415
+ if (receipt) {
416
+ const registeredTopic = eth.id('Registered(uint256,string,address)');
417
+ for (const log of receipt.logs) {
418
+ if (log.address.toLowerCase() === erc8004Addr.toLowerCase()
419
+ && log.topics[0] === registeredTopic) {
420
+ // agentId is the first indexed parameter
421
+ agentId = BigInt(log.topics[1]).toString();
422
+ break;
423
+ }
424
+ }
425
+ }
426
+ }
427
+ catch {
428
+ // Event parsing failed — fall back to balanceOf query
429
+ }
430
+ // Fallback: query by balance if event parsing didn't work
431
+ if (!agentId) {
432
+ const balance = await erc8004.balanceOf(ownerAddress);
433
+ if (Number(balance) > 0) {
434
+ const lastIndex = Number(balance) - 1;
435
+ agentId = (await erc8004.tokenOfOwnerByIndex(ownerAddress, lastIndex)).toString();
436
+ }
437
+ }
438
+ if (agentId) {
439
+ publishMetadata.agent_id = agentId;
440
+ publishMetadata.did = `did:ethr:84532:${ownerAddress}`;
441
+ }
442
+ }
443
+ // Fallback: check AgentRegistry if ERC-8004 didn't yield an agent_id
444
+ if (!publishMetadata.agent_id) {
445
+ const registryAddr = net.contracts.agentRegistry;
446
+ if (registryAddr) {
447
+ const { AgentRegistryClient: ARC } = await Promise.resolve().then(() => __importStar(require('../../registry/AgentRegistryClient')));
448
+ const regClient = ARC.readOnly(registryAddr, prov);
449
+ const onChainConfig = await regClient.getConfig(ownerAddress);
450
+ if (onChainConfig.isActive) {
451
+ const agentId = BigInt(ownerAddress).toString();
452
+ publishMetadata.agent_id = agentId;
453
+ publishMetadata.did = `did:ethr:84532:${ownerAddress}`;
454
+ }
455
+ }
456
+ }
457
+ }
458
+ catch {
459
+ // Best-effort — agent_id will be written on re-publish
460
+ }
461
+ }
462
+ // ================================================================
463
+ // Phase 1: API upsert to agirails.app (post-chain, non-blocking)
464
+ // Uses agent_id from YAML or freshly minted (publishMetadata).
465
+ // API routes: POST /api/v1/agents (dual auth: session + wallet-sig)
466
+ // ================================================================
467
+ const effectiveAgentId = v4Config?.agent_id || publishMetadata.agent_id;
468
+ if (v4Config && effectiveAgentId && walletAddress) {
469
+ const apiSpinner = output.spinner('Syncing with agirails.app...');
470
+ try {
471
+ const publishTimestamp = Math.floor(Date.now() / 1000);
472
+ // C-2 fix: include network in signed message to prevent cross-network replay
473
+ // Upsert only fires after testnet activation, so network is always base-sepolia
474
+ const publishNetwork = 'base-sepolia';
475
+ const upsertMessage = `agirails-publish:${v4Config.slug}:${configHash}:${publishNetwork}:${publishTimestamp}`;
476
+ const { resolvePrivateKey: resolveKey } = await Promise.resolve().then(() => __importStar(require('../../wallet/keystore')));
477
+ const privKey = await resolveKey(projectRoot, { network: 'testnet' });
478
+ if (privKey) {
479
+ const signer = new ethers_1.ethers.Wallet(privKey);
480
+ const sig = await signer.signMessage(upsertMessage);
481
+ const apiResult = await (0, agirailsApp_1.upsertAgent)({
482
+ slug: v4Config.slug,
483
+ agentId: effectiveAgentId,
484
+ wallet: smartWalletAddress || existingWallet || walletAddress,
485
+ signer: walletAddress, // EOA that signed the message
486
+ configCid: cid,
487
+ configHash,
488
+ signature: sig,
489
+ message: upsertMessage,
490
+ timestamp: publishTimestamp,
491
+ network: publishNetwork,
492
+ config: {
493
+ name: v4Config.name,
494
+ description: (v4Config.description || "").replace(/^#\s+[^\n]+\n*/, "").trim(),
495
+ capabilities: v4Config.services,
496
+ pricing: {
497
+ model: "fixed",
498
+ amount: String(v4Config.pricing.base),
499
+ unit: v4Config.pricing.unit || "job",
500
+ currency: v4Config.pricing.currency || "USDC",
501
+ minimum: String(v4Config.pricing.min_price ?? v4Config.pricing.base),
502
+ },
503
+ sla: {
504
+ availability: "24/7",
505
+ responseTime: { p50: 30, p95: 300 },
506
+ ...(v4Config.sla.concurrency ? { throughput: v4Config.sla.concurrency + " concurrent" } : {}),
507
+ },
508
+ ...(v4Config.sla.concurrency ? { concurrency: v4Config.sla.concurrency } : {}),
509
+ payment_mode: v4Config.payment.modes.includes("x402") ? "x402" : "actp",
510
+ network: v4Config.network,
511
+ // Covenant: map V4 accepts/returns to web input/output format
512
+ ...(v4Config.covenant.accepts && Object.keys(v4Config.covenant.accepts).length > 0 ? {
513
+ covenant: {
514
+ input: Object.entries(v4Config.covenant.accepts).map(([k, v]) => k + ": " + v).join("\n"),
515
+ output: Object.entries(v4Config.covenant.returns).map(([k, v]) => k + ": " + v).join("\n"),
516
+ guarantees: [],
517
+ dispute: { window_hours: 24, resolution: "auto-refund" },
518
+ },
519
+ } : {}),
520
+ // Endpoint: for x402 agents
521
+ ...(v4Config.endpoint ? {
522
+ endpoints: { execute: v4Config.endpoint },
523
+ } : {}),
524
+ },
525
+ });
526
+ apiSpinner.stop(true);
527
+ output.success(`Profile live at: agirails.app/a/${v4Config.slug}`);
528
+ // Display claim code if returned (for linking to dashboard)
529
+ if (apiResult.claimCode) {
530
+ output.print(` Claim code: ${apiResult.claimCode}`);
531
+ output.print(` Claim link: https://agirails.app/claim?code=${apiResult.claimCode}`);
532
+ output.print(' (use this to link the agent to your dashboard account)');
533
+ }
534
+ }
535
+ else {
536
+ apiSpinner.stop(false);
537
+ output.info('Skipped agirails.app sync (no wallet key for signing).');
538
+ }
539
+ }
540
+ catch (apiErr) {
541
+ apiSpinner.stop(false);
542
+ // Non-blocking — agent is already on-chain
543
+ output.warning(`agirails.app sync failed: ${apiErr.message}`);
544
+ output.print(' Agent is on-chain. Retry with: actp publish');
545
+ }
546
+ }
547
+ else if (v4Config && !v4Config.agent_id) {
548
+ output.info('First publish — agirails.app sync will happen on re-publish (after agent_id is assigned).');
549
+ }
286
550
  // Update AGIRAILS.md frontmatter
287
551
  const updatedFrontmatter = {
288
552
  ...frontmatter,
@@ -290,9 +554,25 @@ async function runPublish(filePath, options, output) {
290
554
  config_cid: cid,
291
555
  published_at: new Date().toISOString(),
292
556
  ...(arweaveTxId ? { arweave_tx: arweaveTxId } : {}),
557
+ ...publishMetadata,
293
558
  };
294
559
  const updatedContent = (0, agirailsmd_1.serializeAgirailsMd)(updatedFrontmatter, body);
295
560
  (0, fs_1.writeFileSync)(resolvedPath, updatedContent, 'utf-8');
561
+ // Update identity pointer in config.json if this is a {slug}.md file
562
+ if (v4Config) {
563
+ try {
564
+ const { basename } = await Promise.resolve().then(() => __importStar(require('path')));
565
+ const config = (0, config_1.loadConfig)(projectRoot);
566
+ const filename = basename(resolvedPath);
567
+ if (config.identity !== filename) {
568
+ config.identity = filename;
569
+ (0, config_1.saveConfig)(config, projectRoot);
570
+ }
571
+ }
572
+ catch {
573
+ // Best-effort — config might not exist yet
574
+ }
575
+ }
296
576
  // Output results
297
577
  output.result({
298
578
  configHash,
@@ -310,17 +590,31 @@ async function runPublish(filePath, options, output) {
310
590
  }
311
591
  output.print('');
312
592
  output.print('Mainnet: on-chain activation will happen on your first payment.');
593
+ // Context-aware next steps
594
+ const hasEndpoint = frontmatter.endpoint && frontmatter.endpoint !== publishPipeline_1.PENDING_ENDPOINT;
313
595
  output.print('');
314
596
  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');
597
+ if (!hasEndpoint) {
598
+ output.print(' 1. Set your endpoint: Add "endpoint: https://..." to AGIRAILS.md');
599
+ output.print(' 2. Check endpoint: actp health');
600
+ output.print(' 3. Check your balance: actp balance');
601
+ output.print(' 4. Verify config match: actp diff');
602
+ }
603
+ else {
604
+ output.print(' 1. Check endpoint: actp health');
605
+ output.print(' 2. Check your balance: actp balance');
606
+ output.print(' 3. Verify config match: actp diff');
607
+ }
608
+ // Suggest test payment on testnet
609
+ if (testnetTxHash && v4Config?.slug) {
610
+ output.print('');
611
+ output.print(` Try a test payment: actp pay agirails.app/a/${v4Config.slug} 5`);
612
+ }
317
613
  // Warn if placeholder endpoint
318
- if (!frontmatter.endpoint || frontmatter.endpoint === publishPipeline_1.PENDING_ENDPOINT) {
614
+ if (!hasEndpoint) {
319
615
  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');
616
+ output.warning('No endpoint setyour agent can\'t receive jobs yet.');
617
+ output.print(' Add "endpoint: https://your-agent.com/webhook" to AGIRAILS.md, then: actp publish');
324
618
  }
325
619
  }
326
620
  catch (error) {
@@ -393,7 +687,7 @@ async function activateOnTestnet(projectRoot, configHash, cid, endpoint, service
393
687
  // Already up-to-date on-chain — no activation needed
394
688
  return undefined;
395
689
  }
396
- // Build activation calls
690
+ // Build activation calls (includes ERC-8004 identity mint for scenario A)
397
691
  const activationCalls = buildActivationBatch({
398
692
  scenario,
399
693
  agentRegistryAddress: networkConfig.contracts.agentRegistry,
@@ -401,6 +695,7 @@ async function activateOnTestnet(projectRoot, configHash, cid, endpoint, service
401
695
  configHash,
402
696
  listed: true,
403
697
  ...(scenario === 'A' ? { endpoint, serviceDescriptors } : {}),
698
+ erc8004IdentityRegistry: networkConfig.contracts.erc8004IdentityRegistry,
404
699
  });
405
700
  // Always mint test USDC on testnet (SPEC: "always")
406
701
  const mintCalls = buildTestnetMintBatch(networkConfig.contracts.usdc, smartWalletAddress, '1000000000');
@@ -416,6 +711,6 @@ async function activateOnTestnet(projectRoot, configHash, cid, endpoint, service
416
711
  throw new Error(`Testnet activation UserOp failed: ${receipt.hash}`);
417
712
  }
418
713
  output.success('Minted 1,000 test USDC to Smart Wallet');
419
- return receipt.hash;
714
+ return { txHash: receipt.hash, smartWalletAddress };
420
715
  }
421
716
  //# sourceMappingURL=publish.js.map