@agirails/sdk 2.3.1 → 2.4.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 (77) hide show
  1. package/README.md +10 -12
  2. package/dist/ACTPClient.d.ts +80 -3
  3. package/dist/ACTPClient.d.ts.map +1 -1
  4. package/dist/ACTPClient.js +213 -57
  5. package/dist/ACTPClient.js.map +1 -1
  6. package/dist/adapters/BasicAdapter.d.ts +13 -1
  7. package/dist/adapters/BasicAdapter.d.ts.map +1 -1
  8. package/dist/adapters/BasicAdapter.js +24 -3
  9. package/dist/adapters/BasicAdapter.js.map +1 -1
  10. package/dist/cli/commands/init.d.ts +1 -1
  11. package/dist/cli/commands/init.d.ts.map +1 -1
  12. package/dist/cli/commands/init.js +82 -237
  13. package/dist/cli/commands/init.js.map +1 -1
  14. package/dist/cli/commands/publish.d.ts +11 -3
  15. package/dist/cli/commands/publish.d.ts.map +1 -1
  16. package/dist/cli/commands/publish.js +319 -80
  17. package/dist/cli/commands/publish.js.map +1 -1
  18. package/dist/cli/commands/register.d.ts.map +1 -1
  19. package/dist/cli/commands/register.js +10 -0
  20. package/dist/cli/commands/register.js.map +1 -1
  21. package/dist/cli/utils/config.d.ts +17 -2
  22. package/dist/cli/utils/config.d.ts.map +1 -1
  23. package/dist/cli/utils/config.js +9 -1
  24. package/dist/cli/utils/config.js.map +1 -1
  25. package/dist/cli/utils/wallet.d.ts +31 -0
  26. package/dist/cli/utils/wallet.d.ts.map +1 -0
  27. package/dist/cli/utils/wallet.js +114 -0
  28. package/dist/cli/utils/wallet.js.map +1 -0
  29. package/dist/config/pendingPublish.d.ts +79 -0
  30. package/dist/config/pendingPublish.d.ts.map +1 -0
  31. package/dist/config/pendingPublish.js +167 -0
  32. package/dist/config/pendingPublish.js.map +1 -0
  33. package/dist/config/publishPipeline.d.ts +33 -0
  34. package/dist/config/publishPipeline.d.ts.map +1 -1
  35. package/dist/config/publishPipeline.js +33 -2
  36. package/dist/config/publishPipeline.js.map +1 -1
  37. package/dist/index.d.ts +2 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +7 -3
  40. package/dist/index.js.map +1 -1
  41. package/dist/wallet/AutoWalletProvider.d.ts +2 -1
  42. package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
  43. package/dist/wallet/AutoWalletProvider.js +6 -2
  44. package/dist/wallet/AutoWalletProvider.js.map +1 -1
  45. package/dist/wallet/IWalletProvider.d.ts +4 -2
  46. package/dist/wallet/IWalletProvider.d.ts.map +1 -1
  47. package/dist/wallet/aa/BundlerClient.d.ts.map +1 -1
  48. package/dist/wallet/aa/BundlerClient.js +2 -1
  49. package/dist/wallet/aa/BundlerClient.js.map +1 -1
  50. package/dist/wallet/aa/DualNonceManager.d.ts +2 -1
  51. package/dist/wallet/aa/DualNonceManager.d.ts.map +1 -1
  52. package/dist/wallet/aa/DualNonceManager.js +16 -5
  53. package/dist/wallet/aa/DualNonceManager.js.map +1 -1
  54. package/dist/wallet/aa/PaymasterClient.d.ts.map +1 -1
  55. package/dist/wallet/aa/PaymasterClient.js +2 -1
  56. package/dist/wallet/aa/PaymasterClient.js.map +1 -1
  57. package/dist/wallet/aa/TransactionBatcher.d.ts +54 -0
  58. package/dist/wallet/aa/TransactionBatcher.d.ts.map +1 -1
  59. package/dist/wallet/aa/TransactionBatcher.js +67 -1
  60. package/dist/wallet/aa/TransactionBatcher.js.map +1 -1
  61. package/package.json +1 -1
  62. package/src/ACTPClient.ts +265 -49
  63. package/src/adapters/BasicAdapter.ts +48 -12
  64. package/src/cli/commands/init.ts +81 -281
  65. package/src/cli/commands/publish.ts +354 -87
  66. package/src/cli/commands/register.ts +14 -0
  67. package/src/cli/utils/config.ts +32 -2
  68. package/src/cli/utils/wallet.ts +109 -0
  69. package/src/config/pendingPublish.ts +226 -0
  70. package/src/config/publishPipeline.ts +82 -1
  71. package/src/index.ts +8 -0
  72. package/src/wallet/AutoWalletProvider.ts +7 -2
  73. package/src/wallet/IWalletProvider.ts +4 -2
  74. package/src/wallet/aa/BundlerClient.ts +2 -1
  75. package/src/wallet/aa/DualNonceManager.ts +19 -9
  76. package/src/wallet/aa/PaymasterClient.ts +2 -1
  77. package/src/wallet/aa/TransactionBatcher.ts +113 -0
package/README.md CHANGED
@@ -436,15 +436,14 @@ npm run test:coverage
436
436
  ```typescript
437
437
  import { ServiceDirectory, request, provide } from '@agirails/sdk';
438
438
 
439
- // Register a service
440
- const directory = new ServiceDirectory();
441
- directory.register('text-gen', {
442
- providerAddress: '0x...',
443
- capabilities: ['gpt-4']
444
- });
445
-
446
- // Find providers
447
- const providers = directory.find({ capabilities: ['gpt-4'] });
439
+ // Register a provider for a service
440
+ const { serviceDirectory } = require('@agirails/sdk');
441
+ // serviceDirectory is an in-memory, per-process singleton
442
+ // Provider registers automatically when calling provide()
443
+
444
+ // Find providers for a service
445
+ const providers = serviceDirectory.findProviders('text-gen');
446
+ // Returns string[] of provider addresses
448
447
  ```
449
448
 
450
449
  ### Level 1 - Agent Framework
@@ -456,11 +455,10 @@ import { Agent, AgentConfig } from '@agirails/sdk';
456
455
  const agent = new Agent({
457
456
  name: 'my-agent',
458
457
  network: 'testnet',
459
- services: ['text-generation'],
460
458
  });
461
459
 
462
- // Handle jobs
463
- agent.onJob(async (job) => {
460
+ // Register services via agent.provide()
461
+ agent.provide('text-generation', async (job) => {
464
462
  return { result: `Processed: ${job.input}` };
465
463
  });
466
464
 
@@ -11,10 +11,9 @@
11
11
  *
12
12
  * @example
13
13
  * ```typescript
14
- * // Create client in mock mode
14
+ * // Create client (auto-detects wallet from .actp/keystore.json or env vars)
15
15
  * const client = await ACTPClient.create({
16
16
  * mode: 'mock',
17
- * requesterAddress: '0x1234...',
18
17
  * });
19
18
  *
20
19
  * // Basic API - simplest approach
@@ -34,6 +33,7 @@
34
33
  * const tx = await client.advanced.getTransaction(txId);
35
34
  * ```
36
35
  */
36
+ import { ethers } from 'ethers';
37
37
  import { IACTPRuntime } from './runtime/IACTPRuntime';
38
38
  import { BasicAdapter } from './adapters/BasicAdapter';
39
39
  import { StandardAdapter } from './adapters/StandardAdapter';
@@ -42,6 +42,42 @@ import { UnifiedPayParams, UnifiedPayResult } from './types/adapter';
42
42
  import { EASHelper, EASConfig } from './protocol/EASHelper';
43
43
  import { ReputationReporter } from './erc8004/ReputationReporter';
44
44
  import { IWalletProvider } from './wallet/IWalletProvider';
45
+ import { SmartWalletCall } from './wallet/aa/constants';
46
+ import { ActivationScenario } from './wallet/aa/TransactionBatcher';
47
+ import { PendingPublish } from './config/pendingPublish';
48
+ /**
49
+ * Validates that a state directory path is safe to use.
50
+ *
51
+ * SECURITY: Prevents path traversal attacks by ensuring:
52
+ * 1. No '..' components in the path
53
+ * 2. No symbolic links that could escape the intended directory
54
+ * 3. Path resolves to a location within home directory or current working directory
55
+ *
56
+ * @param stateDirectory - The directory path to validate
57
+ * @throws Error if path is unsafe
58
+ */
59
+ /** On-chain agent state from AgentRegistry. */
60
+ export interface OnChainAgentState {
61
+ registeredAt: bigint;
62
+ configHash: string;
63
+ listed: boolean;
64
+ }
65
+ /**
66
+ * Read the on-chain agent state from AgentRegistry.
67
+ * Returns registeredAt, configHash, and listed fields.
68
+ */
69
+ export declare function getOnChainAgentState(provider: ethers.JsonRpcProvider, registryAddress: string, agentAddress: string): Promise<OnChainAgentState>;
70
+ /**
71
+ * Detect the lazy publish activation scenario.
72
+ *
73
+ * Decision matrix:
74
+ * - A: Not registered + has pending → first-time activation
75
+ * - B1: Registered + pending hash != on-chain hash + not listed → re-publish + list
76
+ * - B2: Registered + pending hash != on-chain hash + already listed → re-publish only
77
+ * - C: Pending hash == on-chain hash → stale pending, delete it
78
+ * - none: No pending publish file
79
+ */
80
+ export declare function detectLazyPublishScenario(onChainState: OnChainAgentState, pendingPublish: PendingPublish | null): ActivationScenario;
45
81
  /**
46
82
  * Supported modes for ACTPClient.
47
83
  *
@@ -358,6 +394,34 @@ export declare class ACTPClient {
358
394
  * @internal
359
395
  */
360
396
  private readonly walletProvider?;
397
+ /**
398
+ * Lazy Publish: Current activation scenario.
399
+ * Set during create(), consumed during first payACTPBatched().
400
+ * @internal
401
+ */
402
+ private lazyScenario;
403
+ /**
404
+ * Lazy Publish: Cached pending publish data.
405
+ * @internal
406
+ */
407
+ private pendingPublish;
408
+ /**
409
+ * AgentRegistry address (for lazy activation calls).
410
+ * @internal
411
+ */
412
+ private agentRegistryAddress?;
413
+ /**
414
+ * Network identifier (e.g. 'base-sepolia', 'base-mainnet').
415
+ * Used for chain-scoped pending-publish file operations.
416
+ * @internal
417
+ */
418
+ private networkId?;
419
+ /**
420
+ * Whether the pending publish config is stale (AGIRAILS.md changed since last publish).
421
+ * When true, getActivationCalls() returns empty to prevent stale config going on-chain.
422
+ * @internal
423
+ */
424
+ private pendingIsStale;
361
425
  /**
362
426
  * Private constructor - use ACTPClient.create() factory method.
363
427
  */
@@ -657,7 +721,7 @@ export declare class ACTPClient {
657
721
  * @example
658
722
  * ```typescript
659
723
  * // Register a custom x402 adapter
660
- * client.registerAdapter(new X402Adapter(client.runtime, requesterAddress));
724
+ * client.registerAdapter(new X402Adapter(requesterAddress, { expectedNetwork, transferFn }));
661
725
  * ```
662
726
  */
663
727
  registerAdapter(adapter: IAdapter): void;
@@ -705,6 +769,19 @@ export declare class ACTPClient {
705
769
  * or sending custom batched transactions.
706
770
  */
707
771
  getWalletProvider(): IWalletProvider | undefined;
772
+ /**
773
+ * Get activation calls for lazy publish.
774
+ *
775
+ * Returns SmartWalletCall[] to prepend to the first payment UserOp,
776
+ * plus an onSuccess callback that deletes pending-publish.json.
777
+ *
778
+ * Returns empty calls if no activation is needed (scenario C/none).
779
+ * @internal
780
+ */
781
+ getActivationCalls(): {
782
+ calls: SmartWalletCall[];
783
+ onSuccess: () => void;
784
+ };
708
785
  /**
709
786
  * Non-blocking drift detection for AGIRAILS.md config.
710
787
  * Checks if local AGIRAILS.md matches on-chain config hash.
@@ -1 +1 @@
1
- {"version":3,"file":"ACTPClient.d.ts","sourceRoot":"","sources":["../src/ACTPClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ACTPClient.d.ts","sourceRoot":"","sources":["../src/ACTPClient.ts"],"names":[],"mappings":"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"}
@@ -12,10 +12,9 @@
12
12
  *
13
13
  * @example
14
14
  * ```typescript
15
- * // Create client in mock mode
15
+ * // Create client (auto-detects wallet from .actp/keystore.json or env vars)
16
16
  * const client = await ACTPClient.create({
17
17
  * mode: 'mock',
18
- * requesterAddress: '0x1234...',
19
18
  * });
20
19
  *
21
20
  * // Basic API - simplest approach
@@ -59,7 +58,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
59
58
  return result;
60
59
  };
61
60
  Object.defineProperty(exports, "__esModule", { value: true });
62
- exports.ACTPClient = void 0;
61
+ exports.ACTPClient = exports.detectLazyPublishScenario = exports.getOnChainAgentState = void 0;
63
62
  const path = __importStar(require("path"));
64
63
  const os = __importStar(require("os"));
65
64
  const fs = __importStar(require("fs"));
@@ -76,29 +75,15 @@ const ReputationReporter_1 = require("./erc8004/ReputationReporter");
76
75
  const networks_1 = require("./config/networks");
77
76
  const EOAWalletProvider_1 = require("./wallet/EOAWalletProvider");
78
77
  const AutoWalletProvider_1 = require("./wallet/AutoWalletProvider");
78
+ const TransactionBatcher_1 = require("./wallet/aa/TransactionBatcher");
79
+ const pendingPublish_1 = require("./config/pendingPublish");
79
80
  const Logger_1 = require("./utils/Logger");
80
- // ============================================================================
81
- // Security: Path Validation
82
- // ============================================================================
83
- /**
84
- * Validates that a state directory path is safe to use.
85
- *
86
- * SECURITY: Prevents path traversal attacks by ensuring:
87
- * 1. No '..' components in the path
88
- * 2. No symbolic links that could escape the intended directory
89
- * 3. Path resolves to a location within home directory or current working directory
90
- *
91
- * @param stateDirectory - The directory path to validate
92
- * @throws Error if path is unsafe
93
- */
81
+ const ZERO_HASH = '0x' + '0'.repeat(64);
94
82
  /**
95
- * Check if an agent is registered on AgentRegistry.
96
- * Lightweight read-only check no signer needed.
97
- *
98
- * Uses minimal ABI fragment to avoid importing the full AgentRegistry class.
99
- * Checks registeredAt field of AgentProfile struct (> 0 means registered).
83
+ * Read the on-chain agent state from AgentRegistry.
84
+ * Returns registeredAt, configHash, and listed fields.
100
85
  */
101
- async function checkRegistration(provider, registryAddress, agentAddress) {
86
+ async function getOnChainAgentState(provider, registryAddress, agentAddress) {
102
87
  const contract = new ethers_1.ethers.Contract(registryAddress, [
103
88
  'function getAgent(address agentAddress) view returns ' +
104
89
  '(tuple(address agentAddress, string did, string endpoint, bytes32[] serviceTypes, ' +
@@ -107,8 +92,42 @@ async function checkRegistration(provider, registryAddress, agentAddress) {
107
92
  'uint256 updatedAt, bool isActive, bytes32 configHash, string configCID, bool listed))',
108
93
  ], provider);
109
94
  const profile = await contract.getAgent(agentAddress);
110
- return profile.registeredAt > 0n;
95
+ return {
96
+ registeredAt: profile.registeredAt,
97
+ configHash: profile.configHash,
98
+ listed: profile.listed,
99
+ };
100
+ }
101
+ exports.getOnChainAgentState = getOnChainAgentState;
102
+ /**
103
+ * Detect the lazy publish activation scenario.
104
+ *
105
+ * Decision matrix:
106
+ * - A: Not registered + has pending → first-time activation
107
+ * - B1: Registered + pending hash != on-chain hash + not listed → re-publish + list
108
+ * - B2: Registered + pending hash != on-chain hash + already listed → re-publish only
109
+ * - C: Pending hash == on-chain hash → stale pending, delete it
110
+ * - none: No pending publish file
111
+ */
112
+ function detectLazyPublishScenario(onChainState, pendingPublish) {
113
+ if (!pendingPublish)
114
+ return 'none';
115
+ const isRegistered = onChainState.registeredAt > 0n;
116
+ const pendingHash = pendingPublish.configHash;
117
+ const onChainHash = onChainState.configHash;
118
+ if (!isRegistered) {
119
+ // Not registered — scenario A: full activation
120
+ return 'A';
121
+ }
122
+ // Registered — check if pending hash differs from on-chain
123
+ if (pendingHash !== onChainHash) {
124
+ // Config differs — need to publish
125
+ return onChainState.listed ? 'B2' : 'B1';
126
+ }
127
+ // Hash matches — stale pending
128
+ return 'C';
111
129
  }
130
+ exports.detectLazyPublishScenario = detectLazyPublishScenario;
112
131
  function validateStateDirectory(stateDirectory) {
113
132
  // Check for path traversal characters
114
133
  if (stateDirectory.includes('..')) {
@@ -224,13 +243,34 @@ class ACTPClient {
224
243
  /**
225
244
  * Private constructor - use ACTPClient.create() factory method.
226
245
  */
227
- constructor(runtime, requesterAddress, info, easHelper, erc8004Bridge, reputationReporter, walletProvider, contractAddresses) {
246
+ constructor(runtime, requesterAddress, info, easHelper, erc8004Bridge, reputationReporter, walletProvider, contractAddresses, lazyScenario = 'none', pendingPublish = null, agentRegistryAddress, networkId) {
247
+ /**
248
+ * Lazy Publish: Current activation scenario.
249
+ * Set during create(), consumed during first payACTPBatched().
250
+ * @internal
251
+ */
252
+ this.lazyScenario = 'none';
253
+ /**
254
+ * Lazy Publish: Cached pending publish data.
255
+ * @internal
256
+ */
257
+ this.pendingPublish = null;
258
+ /**
259
+ * Whether the pending publish config is stale (AGIRAILS.md changed since last publish).
260
+ * When true, getActivationCalls() returns empty to prevent stale config going on-chain.
261
+ * @internal
262
+ */
263
+ this.pendingIsStale = false;
228
264
  this.runtime = runtime;
229
265
  this.info = info;
230
266
  this.easHelper = easHelper;
231
267
  this.reputationReporter = reputationReporter;
232
268
  this.walletProvider = walletProvider;
233
- this.basic = new BasicAdapter_1.BasicAdapter(runtime, requesterAddress, easHelper, walletProvider, contractAddresses);
269
+ this.lazyScenario = lazyScenario;
270
+ this.pendingPublish = pendingPublish;
271
+ this.agentRegistryAddress = agentRegistryAddress;
272
+ this.networkId = networkId;
273
+ this.basic = new BasicAdapter_1.BasicAdapter(runtime, requesterAddress, easHelper, walletProvider, contractAddresses, this);
234
274
  this.standard = new StandardAdapter_1.StandardAdapter(runtime, requesterAddress, easHelper);
235
275
  // Initialize registry and router
236
276
  this.registry = new AdapterRegistry_1.AdapterRegistry();
@@ -284,6 +324,10 @@ class ACTPClient {
284
324
  let walletProvider;
285
325
  let requesterAddress;
286
326
  let contractAddresses;
327
+ let lazyScenario = 'none';
328
+ let lazyPending = null;
329
+ let registryAddr;
330
+ let networkId;
287
331
  // If custom runtime provided, use it directly
288
332
  if (config.runtime) {
289
333
  // Custom runtime: requesterAddress is mandatory
@@ -301,15 +345,17 @@ class ACTPClient {
301
345
  // Initialize runtime based on mode
302
346
  switch (config.mode) {
303
347
  case 'mock': {
304
- // Mock mode: requesterAddress is mandatory
305
- if (!config.requesterAddress) {
306
- throw new Error('requesterAddress is required for mock mode');
348
+ // Mock mode: requesterAddress is optional (auto-generate if missing)
349
+ if (config.requesterAddress) {
350
+ if (!/^0x[a-fA-F0-9]{40}$/.test(config.requesterAddress)) {
351
+ throw new Error(`Invalid requesterAddress: "${config.requesterAddress}". ` +
352
+ 'Must be a valid Ethereum address (0x-prefixed, 40 hex chars)');
353
+ }
354
+ requesterAddress = config.requesterAddress;
307
355
  }
308
- if (!/^0x[a-fA-F0-9]{40}$/.test(config.requesterAddress)) {
309
- throw new Error(`Invalid requesterAddress: "${config.requesterAddress}". ` +
310
- 'Must be a valid Ethereum address (0x-prefixed, 40 hex chars)');
356
+ else {
357
+ requesterAddress = ethers_1.ethers.Wallet.createRandom().address;
311
358
  }
312
- requesterAddress = config.requesterAddress;
313
359
  // SECURITY FIX: Enhanced path validation to prevent path traversal attacks
314
360
  if (config.stateDirectory) {
315
361
  validateStateDirectory(config.stateDirectory);
@@ -323,12 +369,25 @@ class ACTPClient {
323
369
  }
324
370
  case 'testnet':
325
371
  case 'mainnet': {
326
- // Validate required parameters for blockchain modes
372
+ // Auto-detect private key from keystore / env var if not provided
327
373
  if (!config.privateKey) {
328
- throw new Error(`privateKey is required for ${config.mode} mode`);
374
+ const { resolvePrivateKey } = await Promise.resolve().then(() => __importStar(require('./wallet/keystore')));
375
+ const resolved = await resolvePrivateKey(config.stateDirectory);
376
+ if (resolved) {
377
+ config = { ...config, privateKey: resolved };
378
+ }
379
+ else {
380
+ throw new Error(`No wallet found for ${config.mode} mode.\n\n` +
381
+ 'Provide a private key via one of:\n' +
382
+ ' 1. ACTP_KEY_PASSWORD env var + .actp/keystore.json (recommended)\n' +
383
+ ' 2. ACTP_PRIVATE_KEY env var\n' +
384
+ ' 3. privateKey option in ACTPClient.create()\n' +
385
+ ' 4. Run "actp publish" to generate a wallet automatically');
386
+ }
329
387
  }
330
388
  // Map mode to network config
331
389
  const network = config.mode === 'testnet' ? 'base-sepolia' : 'base-mainnet';
390
+ networkId = network;
332
391
  const networkConfig = (0, networks_1.getNetwork)(network);
333
392
  // Default RPC URL from network config if not provided
334
393
  const rpcUrl = config.rpcUrl ?? networkConfig.rpcUrl;
@@ -338,7 +397,8 @@ class ACTPClient {
338
397
  }
339
398
  // Create ethers provider and signer
340
399
  const provider = new ethers_1.ethers.JsonRpcProvider(rpcUrl);
341
- const signer = new ethers_1.ethers.Wallet(config.privateKey, provider);
400
+ const privateKey = config.privateKey; // Guaranteed by auto-detect above
401
+ const signer = new ethers_1.ethers.Wallet(privateKey, provider);
342
402
  // ====================================================================
343
403
  // AIP-12: Wallet Provider Selection
344
404
  // ====================================================================
@@ -374,40 +434,66 @@ class ACTPClient {
374
434
  backupUrl: networkConfig.aa.paymasterUrls.pimlico,
375
435
  },
376
436
  });
377
- // Check AgentRegistry gasless only for registered agents
437
+ // Check AgentRegistry + Lazy Publish scenario
378
438
  const smartWalletAddress = autoWallet.getAddress();
379
- const agentRegistryAddress = config.contracts?.agentRegistry
439
+ registryAddr = config.contracts?.agentRegistry
380
440
  ?? networkConfig.contracts.agentRegistry;
381
- let isRegistered = false;
382
- if (agentRegistryAddress) {
441
+ // Load pending publish (may be null) — chain-scoped
442
+ try {
443
+ lazyPending = (0, pendingPublish_1.loadPendingPublish)(network);
444
+ }
445
+ catch {
446
+ // Ignore file read errors
447
+ }
448
+ let useAutoWallet = false;
449
+ if (registryAddr) {
383
450
  try {
384
- isRegistered = await checkRegistration(provider, agentRegistryAddress, smartWalletAddress);
451
+ const onChainState = await getOnChainAgentState(provider, registryAddr, smartWalletAddress);
452
+ lazyScenario = detectLazyPublishScenario(onChainState, lazyPending);
453
+ // Scenario C: stale pending — delete immediately
454
+ if (lazyScenario === 'C') {
455
+ (0, pendingPublish_1.deletePendingPublish)(network);
456
+ lazyPending = null;
457
+ lazyScenario = 'none';
458
+ }
459
+ // Gate: configHash != ZERO || hasPendingPublish → use AutoWallet
460
+ const hasOnChainConfig = onChainState.configHash !== ZERO_HASH;
461
+ const hasPendingPublish = lazyPending !== null;
462
+ if (hasOnChainConfig || hasPendingPublish) {
463
+ useAutoWallet = true;
464
+ }
385
465
  }
386
466
  catch {
387
- // Registry check failed (e.g. RPC down) — allow AA anyway.
388
- // Rationale: don't punish legit registered agents for infra issues.
389
- // Paymaster contract allowlist + rate limits prevent abuse.
390
- isRegistered = true;
391
- Logger_1.sdkLogger.warn('AgentRegistry check failed, proceeding with AA wallet');
467
+ // Registry check failed (e.g. RPC down).
468
+ // Fail-open only if pending publish exists (agent did `actp publish` → legitimate intent).
469
+ // Fail-closed otherwise to prevent unregistered agents getting free gas.
470
+ if (lazyPending) {
471
+ useAutoWallet = true;
472
+ Logger_1.sdkLogger.warn('AgentRegistry check failed, but pending publish found — proceeding with AA.');
473
+ }
474
+ else {
475
+ Logger_1.sdkLogger.warn('AgentRegistry check failed and no pending publish — falling back to EOA.');
476
+ }
392
477
  }
393
478
  }
394
479
  else {
395
480
  // No registry deployed — skip check (early testnet)
396
- isRegistered = true;
481
+ useAutoWallet = true;
397
482
  }
398
- if (isRegistered) {
483
+ if (useAutoWallet) {
399
484
  walletProvider = autoWallet;
400
485
  requesterAddress = smartWalletAddress;
401
486
  }
402
487
  else {
403
- // Not registered — fall back to EOA with warning
404
- Logger_1.sdkLogger.warn('Agent not registered on AgentRegistry. ' +
488
+ // Not published and no pending — fall back to EOA with warning
489
+ Logger_1.sdkLogger.warn('Agent not published on AgentRegistry and no pending publish found. ' +
405
490
  'Falling back to EOA wallet (gas not sponsored). ' +
406
- 'Run "actp register" for gas-free transactions.');
491
+ 'Run "actp publish" for gas-free transactions.');
407
492
  walletProvider = new EOAWalletProvider_1.EOAWalletProvider(signer, networkConfig.chainId);
408
- // Force signer.address — config.requesterAddress may be the Smart Wallet
409
- // address (set by `actp init --wallet auto`), which would be wrong for EOA.
410
493
  requesterAddress = signer.address;
494
+ // Reset since we're not using auto wallet
495
+ lazyScenario = 'none';
496
+ lazyPending = null;
411
497
  }
412
498
  }
413
499
  else {
@@ -472,8 +558,29 @@ class ACTPClient {
472
558
  stateDirectory,
473
559
  walletTier: walletProvider?.getWalletInfo().tier,
474
560
  };
475
- // Pass wallet provider and contract addresses to constructor
476
- const client = new ACTPClient(runtime, normalizedAddress, info, easHelper, erc8004Bridge, reputationReporter, walletProvider, contractAddresses);
561
+ // Staleness check: recompute hash if AGIRAILS.md exists and we have a pending publish
562
+ let pendingIsStale = false;
563
+ if (lazyPending && lazyScenario !== 'none' && lazyScenario !== 'C') {
564
+ try {
565
+ const mdPath = path.join(process.cwd(), 'AGIRAILS.md');
566
+ if (fs.existsSync(mdPath)) {
567
+ const { computeConfigHash } = await Promise.resolve().then(() => __importStar(require('./config/agirailsmd')));
568
+ const content = fs.readFileSync(mdPath, 'utf-8');
569
+ const { configHash: currentHash } = computeConfigHash(content);
570
+ if (currentHash !== lazyPending.configHash) {
571
+ pendingIsStale = true;
572
+ Logger_1.sdkLogger.warn('AGIRAILS.md changed since last publish. Activation skipped. ' +
573
+ 'Run "actp publish" to update.');
574
+ }
575
+ }
576
+ }
577
+ catch {
578
+ // Best-effort: staleness check should not block operation
579
+ }
580
+ }
581
+ // Pass wallet provider, contract addresses, and lazy publish state to constructor
582
+ const client = new ACTPClient(runtime, normalizedAddress, info, easHelper, erc8004Bridge, reputationReporter, walletProvider, contractAddresses, lazyScenario, lazyPending, registryAddr, networkId);
583
+ client.pendingIsStale = pendingIsStale;
477
584
  // Drift detection: non-blocking check for AGIRAILS.md sync status
478
585
  if (config.mode !== 'mock') {
479
586
  client.checkConfigDrift(config).catch(() => {
@@ -844,7 +951,7 @@ class ACTPClient {
844
951
  * @example
845
952
  * ```typescript
846
953
  * // Register a custom x402 adapter
847
- * client.registerAdapter(new X402Adapter(client.runtime, requesterAddress));
954
+ * client.registerAdapter(new X402Adapter(requesterAddress, { expectedNetwork, transferFn }));
848
955
  * ```
849
956
  */
850
957
  registerAdapter(adapter) {
@@ -900,6 +1007,48 @@ class ACTPClient {
900
1007
  getWalletProvider() {
901
1008
  return this.walletProvider;
902
1009
  }
1010
+ /**
1011
+ * Get activation calls for lazy publish.
1012
+ *
1013
+ * Returns SmartWalletCall[] to prepend to the first payment UserOp,
1014
+ * plus an onSuccess callback that deletes pending-publish.json.
1015
+ *
1016
+ * Returns empty calls if no activation is needed (scenario C/none).
1017
+ * @internal
1018
+ */
1019
+ getActivationCalls() {
1020
+ if (this.lazyScenario === 'none' || this.lazyScenario === 'C' || !this.agentRegistryAddress) {
1021
+ return { calls: [], onSuccess: () => { } };
1022
+ }
1023
+ // Staleness check: AGIRAILS.md changed since last publish → skip activation
1024
+ if (this.pendingIsStale) {
1025
+ return { calls: [], onSuccess: () => { } };
1026
+ }
1027
+ const pending = this.pendingPublish;
1028
+ if (!pending) {
1029
+ return { calls: [], onSuccess: () => { } };
1030
+ }
1031
+ // Build activation batch params
1032
+ const params = {
1033
+ scenario: this.lazyScenario,
1034
+ agentRegistryAddress: this.agentRegistryAddress,
1035
+ cid: pending.cid,
1036
+ configHash: pending.configHash,
1037
+ listed: true,
1038
+ };
1039
+ // For scenario A, extract registration params from pending publish
1040
+ if (this.lazyScenario === 'A') {
1041
+ params.endpoint = pending.endpoint;
1042
+ params.serviceDescriptors = pending.serviceDescriptors;
1043
+ }
1044
+ const calls = (0, TransactionBatcher_1.buildActivationBatch)(params);
1045
+ const onSuccess = () => {
1046
+ (0, pendingPublish_1.deletePendingPublish)(this.networkId);
1047
+ this.lazyScenario = 'none';
1048
+ this.pendingPublish = null;
1049
+ };
1050
+ return { calls, onSuccess };
1051
+ }
903
1052
  /**
904
1053
  * Non-blocking drift detection for AGIRAILS.md config.
905
1054
  * Checks if local AGIRAILS.md matches on-chain config hash.
@@ -913,7 +1062,14 @@ class ACTPClient {
913
1062
  // Look for AGIRAILS.md in cwd
914
1063
  const agirailsMdPath = join(process.cwd(), 'AGIRAILS.md');
915
1064
  if (!existsSync(agirailsMdPath)) {
916
- return; // No local file — nothing to check
1065
+ // No local file — try cached hash from pending-publish.json
1066
+ const { loadPendingPublish: loadPP } = await Promise.resolve().then(() => __importStar(require('./config/pendingPublish')));
1067
+ const driftNetwork = config.mode === 'testnet' ? 'base-sepolia' : 'base-mainnet';
1068
+ const pp = loadPP(driftNetwork);
1069
+ if (pp) {
1070
+ Logger_1.sdkLogger.info('[AGIRAILS] No AGIRAILS.md found, using cached config hash from pending-publish.json');
1071
+ }
1072
+ return;
917
1073
  }
918
1074
  const network = config.mode === 'testnet' ? 'base-sepolia' : 'base-mainnet';
919
1075
  const networkConfig = (0, networks_1.getNetwork)(network);