diff --git a/src/ACTPClient.ts b/src/ACTPClient.ts index 3090411..1c4d9d9 100644 --- a/src/ACTPClient.ts +++ b/src/ACTPClient.ts @@ -1805,6 +1805,18 @@ export class ACTPClient { (agentBlock && typeof agentBlock.slug === 'string' ? agentBlock.slug : undefined) || (fileSlug !== 'AGIRAILS' ? fileSlug : undefined); + // AIP-18 DEC-3: a pure buyer (intent: pay) is never anchored on-chain — + // its config lives in the local file + the agirails.app DB, not the + // AgentRegistry. Chain-based drift/reconcile does not apply, so skip it + // rather than emit a misleading "not published / config ahead" warning + // on every client startup. (DB-based buyer reconcile is future work.) + const intentVal = + (typeof frontmatter.intent === 'string' ? frontmatter.intent : undefined) || + (agentBlock && typeof agentBlock.intent === 'string' ? agentBlock.intent : undefined); + if (intentVal?.toLowerCase() === 'pay') { + return; + } + const autoSync = process.env.ACTP_AUTO_SYNC !== '0' && process.env.ACTP_AUTO_SYNC !== 'false'; diff --git a/src/cli/commands/publish.ts b/src/cli/commands/publish.ts index 403457c..23befdd 100644 --- a/src/cli/commands/publish.ts +++ b/src/cli/commands/publish.ts @@ -563,6 +563,22 @@ async function runPublish( 'Pay-only agent: skipping on-chain registration. ' + 'Identity is your wallet + agirails.app profile.' ); + + // Resolve the Smart Wallet address for a wallet:auto buyer so the DB + // link (and the buyer-link marker) record the address the agent actually + // transacts from — not the bare EOA signer. Providers get this from + // on-chain activation; a buyer skips activation, so read the address + // `actp init` derived into .actp/config.json. (Falls back to the EOA if + // unknown.) This makes buyer attribution match on-chain payments. + try { + const cfg = loadConfig(projectRoot); + if (cfg.wallet === 'auto' && cfg.smartWallet) { + smartWalletAddress = cfg.smartWallet; + } + } catch { + // Best-effort — the EOA fallback below still produces a valid link. + } + // Write the buyer-link marker so the SDK's auto-wallet gate grants // gas-sponsored transactions to this linked buyer (AIP-18 DEC-8) — a // buyer has no on-chain configHash and no pending-publish, so without @@ -579,7 +595,7 @@ async function runPublish( { version: 1, slug: v4Config!.slug, - wallet: (walletAddress || '').toLowerCase(), + wallet: (smartWalletAddress || walletAddress || '').toLowerCase(), linkedAt: new Date().toISOString(), }, buyerLinkActpDir, @@ -753,6 +769,13 @@ async function runPublish( // the next re-publish. intent: v4Config.intent, capabilities: v4Config.services.map(s => s.type), + // Buyer-side discovery metadata (AIP-18 §7.1, opt-in semi-public) + // so the dashboard/profile reflects what the buyer requests. + // budget is deliberately NOT synced — it is a private operational + // cap (DEC-2) and never leaves the owner's machine. + ...(v4Config.servicesNeeded?.length + ? { services_needed: v4Config.servicesNeeded } + : {}), pricing: { model: "fixed", amount: String(v4Config.pricing.base),