{"_id":"@amorce/sdk","_rev":"2-32dd651c2b70a097c789195cff14585f","name":"@amorce/sdk","dist-tags":{"latest":"3.1.0"},"versions":{"3.0.0":{"name":"@amorce/sdk","version":"3.0.0","keywords":["amorce","agent","protocol","aatp","sdk","ai-agents","zero-trust"],"author":{"name":"Athena Architecture"},"license":"MIT","_id":"@amorce/sdk@3.0.0","maintainers":[{"name":"amorce","email":"robert.gosselin@gmail.com"}],"dist":{"shasum":"349e86d113af0f5b8aedbabb9a6c15f22710c2dd","tarball":"https://registry.npmjs.org/@amorce/sdk/-/sdk-3.0.0.tgz","fileCount":758,"integrity":"sha512-POq7Ecayvtrv8HHDDZQjisyluwlVaO76vTu7QvrIEZNLiUQ7+xGXbobyj3Dirua/vCR9MeOtbxOiv/ogh7PnkQ==","signatures":[{"sig":"MEUCIGM68HYR06FntXKTf0M89fYEM6aTj8wPNje2Qcl3raCwAiEA77nV/iDSvgeJVrRsk1oVeGWs+fMaMElZeVTJZ2I9W6k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48409521},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"07fd578e1c69aedc9c597f78c7197a652e4feb91","scripts":{"lint":"eslint src/","test":"jest","build":"tsup"},"_npmUser":{"name":"amorce","email":"robert.gosselin@gmail.com"},"_npmVersion":"10.9.2","description":"Official TypeScript/JavaScript SDK for the Amorce Agent Transaction Protocol (AATP) with HITL and MCP support","directories":{},"_nodeVersion":"22.16.0","dependencies":{"uuid":"^9.0.1","undici":"^6.0.0","p-retry":"^6.0.0","libsodium-wrappers":"^0.7.13","fast-json-stable-stringify":"^2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","tsup":"^8.0.2","eslint":"^8.57.0","ts-jest":"^29.1.2","ts-node":"^10.9.2","typescript":"^5.3.3","@types/jest":"^29.5.12","@types/node":"^20.19.25","@types/uuid":"^9.0.8","@types/libsodium-wrappers":"^0.7.14","@typescript-eslint/parser":"^7.1.0","@typescript-eslint/eslint-plugin":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_3.0.0_1765119110107_0.16605278648153865","host":"s3://npm-registry-packages-npm-production"}},"3.1.0":{"name":"@amorce/sdk","version":"3.1.0","description":"Official TypeScript/JavaScript SDK for the Amorce Agent Transaction Protocol (AATP) with HITL and MCP support","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"tsup","test":"jest","lint":"eslint src/"},"keywords":["amorce","agent","protocol","aatp","sdk","ai-agents","zero-trust"],"author":{"name":"Athena Architecture"},"license":"MIT","dependencies":{"undici":"^6.0.0","p-retry":"^6.0.0","fast-json-stable-stringify":"^2.1.0","libsodium-wrappers":"^0.7.13","uuid":"^9.0.1"},"devDependencies":{"@types/jest":"^29.5.12","@types/libsodium-wrappers":"^0.7.14","@types/node":"^20.19.25","@types/uuid":"^9.0.8","@typescript-eslint/eslint-plugin":"^7.1.0","@typescript-eslint/parser":"^7.1.0","eslint":"^8.57.0","jest":"^29.7.0","ts-jest":"^29.1.2","ts-node":"^10.9.2","tsup":"^8.0.2","typescript":"^5.3.3"},"_id":"@amorce/sdk@3.1.0","gitHead":"d018bf89f6e686de4201a1d55e0b825df6f4265b","_nodeVersion":"22.16.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-CEcNj1af7EtwHXd/QrUbkzCpN6O4RIzui3oz8oXGAs2OyCKyHnSTLmQSIm0Zzo89LATnAKeb/9HzMIM6zy0deA==","shasum":"a973f5c251ddf8cc463352fac452ca3d064dcbe3","tarball":"https://registry.npmjs.org/@amorce/sdk/-/sdk-3.1.0.tgz","fileCount":34,"unpackedSize":131619,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBd9gAmFPfaOS4PEGQ/XElabTKwbTwZ9m95EYaQyG3/4AiA0DakruWhOQ7acthX+GNfZWbQN8O2lxfC5FU9Tkxz+Mw=="}]},"_npmUser":{"name":"amorce","email":"robert.gosselin@gmail.com"},"directories":{},"maintainers":[{"name":"amorce","email":"robert.gosselin@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_3.1.0_1765836717426_0.9502334742469776"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-07T14:51:49.981Z","modified":"2025-12-15T22:11:57.771Z","3.0.0":"2025-12-07T14:51:50.847Z","3.1.0":"2025-12-15T22:11:57.586Z"},"author":{"name":"Athena Architecture"},"license":"MIT","keywords":["amorce","agent","protocol","aatp","sdk","ai-agents","zero-trust"],"description":"Official TypeScript/JavaScript SDK for the Amorce Agent Transaction Protocol (AATP) with HITL and MCP support","maintainers":[{"name":"amorce","email":"robert.gosselin@gmail.com"}],"readme":"# Amorce TypeScript/JavaScript SDK (AATP)\n\n[![npm version](https://img.shields.io/npm/v/@amorce/sdk.svg)](https://www.npmjs.com/package/@amorce/sdk)\n[![GitHub](https://img.shields.io/github/stars/trebortGolin/amorce-js-sdk?style=social)](https://github.com/trebortGolin/amorce-js-sdk)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Demo](https://img.shields.io/badge/demo-marketplace-success.svg)](https://github.com/trebortGolin/agent-marketplace-demo)\n\n**Official TypeScript/JavaScript SDK for the Amorce Agent Transaction Protocol (AATP).**\n\n**See it in action**: [Agent Marketplace Demo](https://github.com/trebortGolin/agent-marketplace-demo) - Watch AI agents negotiate with cryptographic security\n\nThe Amorce SDK allows any JavaScript application (Node.js or Browser) to become a verified node in the **Agent Economy**. It provides the cryptographic primitives (Ed25519 via `libsodium`) and the transport layer required to transact securely with AI Agents (OpenAI, Google Gemini, Apple Intelligence).\n\n---\n\n## 🚀 Features\n\n* **Zero-Trust Security**: Every request is cryptographically signed (Ed25519) locally.\n* **Agent Identity**: Manage your agent's identity and keys securely without complexity.\n* **Priority Lane**: Mark critical messages (`high`, `critical`) to bypass network congestion.\n* **HTTP/2 Support (v2.1.0)**: Automatic HTTP/2 via undici for multiplexed connections and better performance.\n* **Exponential Backoff + Jitter (v2.1.0)**: Advanced retry logic via p-retry (handles 429, 503, 504) with randomization to prevent thundering herd.\n* **Idempotency Keys (v2.1.0)**: Auto-generated UUIDv4 for safe retries and transaction deduplication.\n* **Structured Responses (v2.1.0)**: `AmorceResponse` with `isSuccess()` and `isRetryable()` utility methods.\n* **Developer Experience**: Simplified `IdentityManager` with auto-derived Agent IDs and provider pattern.\n* **Robust Error Handling**: Specific exceptions (`AmorceNetworkError`, `AmorceAPIError`) for reliable production code.\n* **Isomorphic**: Works in Node.js (requires Node.js 18+) and Modern Browsers.\n* **Type Safe**: Native TypeScript support for robust development.\n\n---\n\n## 📦 Installation\n\n```bash\nnpm install @amorce/sdk\n```\n\nThe SDK automatically includes all required dependencies (`libsodium-wrappers`, `fast-json-stable-stringify`, `uuid`, `undici`, `p-retry`).\n\n**Requirements:** Node.js 18+ for optimal HTTP/2 support.\n\n---\n\n## ⚡ Quick Start\n\n### 1. Identity Setup\n\nAn Agent is defined by its **Private Key**. Never share this key.\n\n#### Option A: Quick Start (Ephemeral / Testing)\n\nGenerate a new identity in memory instantly. Perfect for QA scripts or temporary bots.\n\n```typescript\nimport { IdentityManager } from '@amorce/sdk';\n\n// Generates a fresh Ed25519 keypair in memory (Ephemeral)\nconst identity = await IdentityManager.generate();\n\n// The Agent ID is automatically derived from the Public Key (SHA-256)\nconsole.log(`Agent ID: ${identity.getAgentId()}`);\nconsole.log(`Public Key: ${identity.getPublicKeyPem()}`);\n```\n\n#### Option B: Production (Secure Storage)\n\nLoad your identity from a secure source or environment variable.\n\n```typescript\nimport { IdentityManager, EnvVarProvider } from '@amorce/sdk';\n\n// Load from Environment Variable (Recommended for production)\nconst provider = new EnvVarProvider('AGENT_PRIVATE_KEY');\nconst identity = await IdentityManager.fromProvider(provider);\n\nconsole.log(`Agent ID: ${identity.getAgentId()}`);\n```\n\n### 2. Sending a Transaction (Full Example)\n\nUse the `AmorceClient` to discover services and execute transactions.\n\n```typescript\nimport { \n  AmorceClient, \n  IdentityManager, \n  PriorityLevel,\n  AmorceNetworkError,\n  AmorceAPIError \n} from '@amorce/sdk';\n\n// Configuration (Use Env Vars in Prod!)\nconst DIRECTORY_URL = process.env.AMORCE_DIRECTORY_URL || 'https://directory.amorce.io';\nconst ORCHESTRATOR_URL = process.env.AMORCE_ORCHESTRATOR_URL || 'https://api.amorce.io';\n\n// 1. Generate or load identity\nconst identity = await IdentityManager.generate();\n\n// 2. Initialize the client\n// Note: 'agent_id' is automatically derived from the identity object.\nconst client = new AmorceClient(\n  identity,\n  DIRECTORY_URL,\n  ORCHESTRATOR_URL\n);\n\n// 3. Define the payload (The \"Letter\" inside the transaction)\nconst payload = {\n  intent: 'book_reservation',\n  params: { date: '2025-10-12', guests: 2 }\n};\n\n// 4. Execute with PRIORITY\n// Options: PriorityLevel.NORMAL, .HIGH, .CRITICAL\nconsole.log(`Sending transaction from ${identity.getAgentId()}...`);\n\ntry {\n  const response = await client.transact(\n    { service_id: 'srv_restaurant_01' },\n    payload,\n    PriorityLevel.HIGH\n  );\n  \n  // v2.1.0: Response is now an AmorceResponse object with utility methods\n  if (response.isSuccess()) {\n    console.log(`✅ Success! Tx ID: ${response.transaction_id}`);\n    console.log(`Data:`, response.result?.data);\n  } else {\n    console.log(`⚠️ Server Error:`, response);\n  }\n} catch (e) {\n  if (e instanceof AmorceNetworkError) {\n    console.error(`❌ Network Error (Retryable):`, e.message);\n  } else if (e instanceof AmorceAPIError) {\n    console.error(`❌ API Error ${e.statusCode}:`, e.responseBody);\n  } else {\n    console.error(`❌ Unexpected Error:`, e);\n  }\n}\n```\n\n### 3. Error Handling\n\nThe SDK provides specific exceptions for robust error handling:\n\n```typescript\nimport { \n  AmorceClient, \n  AmorceConfigError, \n  AmorceNetworkError, \n  AmorceAPIError \n} from '@amorce/sdk';\n\ntry {\n  await client.transact(...);\n} catch (e) {\n  if (e instanceof AmorceConfigError) {\n    console.error('Configuration Error:', e.message);\n  } else if (e instanceof AmorceNetworkError) {\n    console.error('Network Error:', e.message); // Retry might be possible\n  } else if (e instanceof AmorceAPIError) {\n    console.error(`API Error ${e.statusCode}:`, e.responseBody);\n  } else {\n    console.error('Unexpected Error:', e);\n  }\n}\n```\n\n---\n\n## 🛡️ For Builders: Protect Your API\n\n**Are you building an AI Agent?** Use the SDK to verify incoming requests on your server.\n\n### Why This Matters\n\n- ✅ **Cryptographic proof** of sender identity (Ed25519 signatures)\n- ✅ **Zero-trust by default** - every request is verified\n- ✅ **Intent whitelisting** - only allow specific actions  \n- ✅ **Automatic key revocation** - invalid agents rejected instantly\n- ✅ **No maintenance burden** - public keys auto-fetched from Trust Directory\n\n### How to Verify Requests\n\n```typescript\nimport { verifyRequest, AmorceSecurityError } from '@amorce/sdk';\nimport express from 'express';\n\nconst app = express();\n\napp.post('/api/v1/webhook', express.json(), async (req, res) => {\n  try {\n    // ✅ AUTOMATIC VERIFICATION\n    // SDK fetches public key from Trust Directory and verifies signature\n    const verified = await verifyRequest({\n      headers: req.headers,\n      body: JSON.stringify(req.body),\n      allowedIntents: ['book_table', 'check_availability', 'cancel']\n    });\n    \n    console.log(`✅ Verified request from: ${verified.agentId}`);\n    console.log(`Intent: ${verified.payload.payload.intent}`);\n    \n    // Your business logic here - 100% sure it's legitimate\n    if (verified.payload.payload.intent === 'book_table') {\n      return res.json({ status: 'confirmed', table: 'A5', time: '19:00' });\n    }\n    \n  } catch (e) {\n    if (e instanceof AmorceSecurityError) {\n      console.log(`❌ Rejected: ${e.message}`);\n      return res.status(401).json({ error: 'Unauthorized' });\n    }\n    throw e;\n  }\n});\n```\n\n**That's it!** Your API is now protected by cryptographic verification.\n\n### Advanced: Manual Public Key (Offline/Testing)\n\nFor testing or private networks, you can skip the Trust Directory lookup:\n\n```typescript\n// Provide public key directly (no network call)\nconst verified = await verifyRequest({\n  headers: req.headers,\n  body: req.body,\n  publicKey: \"-----BEGIN PUBLIC KEY-----\\n...\\n-----END PUBLIC KEY-----\"\n});\n```\n\n---\n\n## 📋 Register Your Agent (Optional)\n\nWant to list your service in the Amorce Network? Generate your manifest:\n\n```typescript\nconst identity = await IdentityManager.generate();\n\n// 🖨️  Generate manifest JSON\nconst manifest = identity.toManifestJson({\n  name: 'My Restaurant Bot',\n  endpoint: 'https://my-api.example.com/api/v1/webhook',\n  capabilities: ['book_table', 'check_availability', 'cancel_reservation'],\n  description: 'Fine dining reservations with real-time availability'\n});\n\n// Save it\nimport fs from 'fs';\nfs.writeFileSync('agent-manifest.json', manifest);\n\nconsole.log('✅ Manifest created! Submit it to the Trust Directory to get listed.');\n```\n\n**What you get:**\n- 🌐 Discoverable by other agents in the network\n- 🔐 Your public key automatically distributed\n- 📊 Trust score based on transaction history\n\n---\n\n## 🔌 MCP Integration - Production Ready ✅\n\n**Use Model Context Protocol tools through Amorce with cryptographic security and human oversight.**\n\nThe Amorce SDK provides production-ready integration with [Model Context Protocol](https://modelcontextprotocol.io) servers, adding Ed25519 signatures and human-in-the-loop approvals to all tool calls.\n\n### 🚀 Quick Start\n\n```typescript\nimport { IdentityManager, MCPToolClient } from '@amorce/sdk';\n\n// 1. Create your agent identity\nconst identity = await IdentityManager.generate();\n\n// 2. Connect to MCP wrapper\nconst mcp = new MCPToolClient(identity, 'http://localhost:5001');\n\n// 3. Discover available tools\nconst tools = await mcp.listTools();\nfor (const tool of tools) {\n  const hitl = tool.requiresApproval ? '🔒' : '✓';\n  console.log(`${hitl} ${tool.name}: ${tool.description}`);\n}\n\n// 4. Call tools (read operations)\nconst result = await mcp.callTool('filesystem', 'read_file', {\n  path: '/tmp/data.txt'\n});\nconsole.log(result);\n\n// 5. Call tools requiring approval (write operations)\ntry {\n  await mcp.callTool('filesystem', 'write_file', {\n    path: '/tmp/output.txt',\n    content: 'Hello from Amorce!'\n  });\n} catch (error) {\n  console.log('Approval required!');  \n  // Request approval through orchestrator\n  const approvalId = await client.requestApproval({...});  \n  const result = await mcp.callTool('filesystem', 'write_file', {\n    path: '/tmp/output.txt',\n    content: 'Hello!'\n  }, approvalId);\n}\n```\n\n### 📖 Complete Example with HITL\n\n```typescript\nimport { IdentityManager, MCPToolClient, AmorceClient } from '@amorce/sdk';\n\n// Setup\nconst identity = await IdentityManager.generate();\nconst mcp = new MCPToolClient(identity, 'http://localhost:5001');\nconst client = new AmorceClient(\n  identity,\n  'https://directory.amorce.io',\n  'https://api.amorce.io'\n);\n\n// List tools and check HITL requirements\nconst tools = await mcp.listTools();\nconst writeTool = tools.find(t => t.name === 'write_file');\nconsole.log(`Write file requires approval: ${writeTool.requiresApproval}`);  // true\n\n// Attempt without approval (will fail)\ntry {\n  const result = await mcp.callTool('filesystem', 'write_file', {\n    path: '/tmp/important.txt',\n    content: 'Critical data'\n  });\n} catch (error) {\n  console.log(`Blocked: ${error.message}`);  // \"Tool requires approval\"\n}\n    \n// Request approval\nconst approvalId = await client.requestApproval({\n  summary: 'Write ML model output file',\n  details: { path: '/tmp/important.txt', content: 'Critical data' },\n  timeoutSeconds: 300\n});\n\n// Human reviews and approves (via UI or API)\n// ... approval workflow ...\n\n// Execute with approval\nconst result = await mcp.callTool('filesystem', 'write_file', {\n  path: '/tmp/important.txt',\n  content: 'Critical data'\n}, approvalId);\n\nconsole.log(`File written successfully: ${result}`);\n```\n\n### 🎯 Tool Categories\n\n| Category | Examples | HITL Required |\n|----------|----------|---------------|\n| **Read Operations** | read_file, list_directory, search | ❌ No |\n| **Write Operations** | write_file, edit_file | ✅ Yes |\n| **Destructive Operations** | delete_file, move_file | ✅ Yes |\n| **Search/Query** | brave_search, database_query | ❌ No (read-only) |\n\n### 🔗 Available MCP Servers\n\nAccess 80+ production MCP servers through Amorce:\n\n```typescript\n// Filesystem operations\nawait mcp.callTool('filesystem', 'read_file', { path: '/data/input.json' });\n\n// Web search\nawait mcp.callTool('search', 'brave_search', { query: 'AI agents 2024' });\n\n// Database access (with HITL)\nawait mcp.callTool('postgres', 'execute_query', \n  { sql: 'SELECT * FROM users' }, \n  approvalId\n);\n\n// Git operations (with HITL)\nawait mcp.callTool('git', 'commit', \n  { message: 'Update config' }, \n  approvalId\n);\n```\n\n[View all 80+ MCP servers →](https://github.com/modelcontextprotocol/servers)\n\n---\n\n## 🤝 Human-in-the-Loop (HITL) Support\n\nEnable human oversight for critical agent decisions with built-in approval workflows.\n\n### When to Use HITL\n\n- **High-value transactions** - Booking reservations, making purchases\n- **Data sharing** - Before sending personal information to third parties\n- **Irreversible actions** - Cancellations, deletions, confirmations\n- **Regulatory compliance** - Finance, healthcare, legal industries\n\n### Basic HITL Workflow\n\n```typescript\nimport { AmorceClient, IdentityManager } from '@amorce/sdk';\n\nconst identity = await IdentityManager.generate();\nconst client = new AmorceClient(\n  identity,\n  'https://directory.amorce.io',\n  'https://api.amorce.io'\n);\n\n// 1. Agent negotiates with service\nconst response = await client.transact(\n  { service_id: 'srv_restaurant_123' },\n  { intent: 'book_table', guests: 4, date: '2025-12-05' }\n);\n\n// 2. Request human approval before finalizing\nconst approvalId = await client.requestApproval({\n  transactionId: response.transaction_id,\n  summary: `Book table for 4 guests at ${response.restaurant.name}`,\n  details: response.result,\n  timeoutSeconds: 300  // 5 minute timeout\n});\n\nconsole.log(`Awaiting approval: ${approvalId}`);\n\n// 3. Human reviews and approves (via SMS, email, app, etc.)\n// ... your notification logic here ...\n\n// 4. Check approval status\nconst status = await client.checkApproval(approvalId);\nif (status.status === 'approved') {\n  // 5. Finalize the transaction\n  const finalResponse = await client.transact(\n    { service_id: 'srv_restaurant_123' },\n    { intent: 'confirm_booking', booking_id: response.booking_id }\n  );\n  console.log('✅ Booking confirmed!');\n}\n```\n\n### Submitting Approval Decisions\n\nYour application collects human input and submits the decision:\n\n```typescript\n// Human approved via your UI/SMS/voice interface\nawait client.submitApproval({\n  approvalId: approvalId,\n  decision: 'approve',  // or 'reject'\n  approvedBy: 'user@example.com',\n  comments: 'Looks good for the business lunch'\n});\n```\n\n### LLM-Interpreted Approvals\n\nUse AI to interpret natural language responses:\n\n```typescript\nimport { GoogleGenerativeAI } from '@google/generative-ai';\n\n// Human responds: \"yes sounds perfect\"\nconst humanResponse = \"yes sounds perfect\";\n\n// LLM interprets the intent\nconst genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\nconst model = genAI.getGenerativeModel({ model: \"gemini-pro\" });\n\nconst result = await model.generateContent(\n  `Is this approving or rejecting? \"${humanResponse}\" Answer: APPROVE or REJECT`\n);\nconst interpretation = result.response.text();\n\nconst decision = interpretation.includes('APPROVE') ? 'approve' : 'reject';\n\nawait client.submitApproval({\n  approvalId,\n  decision,\n  approvedBy: 'user@example.com',\n  comments: `Original response: ${humanResponse}`\n});\n```\n\n### Channel-Agnostic Notifications\n\nHITL is **protocol-level** - you choose how to notify humans:\n\n- **SMS** (Twilio): \"Sarah wants to book Le Petit Bistro for 4. Reply YES/NO\"\n- **Email**: Send approval link with one-click approve/reject\n- **Voice** (Vapi.ai): \"Your assistant needs approval. Say approve or decline\"\n- **Push notification**: Mobile app notification\n- **Slack/Teams**: Bot message with buttons\n\n**Example with Twilio:**\n```typescript\nimport twilio from 'twilio';\n\nconst client = twilio(accountSid, authToken);\n\n// Create approval\nconst approvalId = await amorceClient.requestApproval({...});\n\n// Send SMS\nawait client.messages.create({\n  to: '+1234567890',\n  from: '+0987654321',\n  body: `Sarah needs approval: Book table for 4 at Le Petit Bistro tomorrow 7pm. Reply YES or NO`\n});\n\n// Poll for response or use webhook\n// When you receive \"YES\", submit approval\nawait amorceClient.submitApproval({\n  approvalId,\n  decision: 'approve',\n  approvedBy: 'sms:+1234567890'\n});\n```\n\n### Advanced: Approval Timeouts\n\nApprovals automatically expire after the timeout period:\n\n```typescript\nconst approvalId = await client.requestApproval({\n  transactionId: txId,\n  summary: 'High-value purchase: $5,000',\n  timeoutSeconds: 600  // 10 minutes\n});\n\n// Later...\nconst status = await client.checkApproval(approvalId);\nif (status.status === 'expired') {\n  console.log('⏱️ Approval request timed out - transaction cancelled');\n}\n```\n\n### Best Practices\n\n1. **Clear summaries** - Make approval requests easy to understand\n2. **Appropriate timeouts** - Balance urgency vs. convenience\n3. **Audit trail** - All approvals are logged with timestamps and user IDs\n4. **Fallback handling** - Handle expired/rejected approvals gracefully\n5. **Security** - Verify human identity before submitting approvals\n\n---\n\n## 🛡️ Architecture & Security\n\nThe SDK implements the **AATP v0.1** standard strictly.\n\n1. **Identity**: Keys are managed via the `IdentityManager` with pluggable providers.\n2. **Canonicalization**: JSON payloads are serialized canonically (RFC 8785) to ensure signature consistency.\n3. **Signing**: Transactions are signed locally using Ed25519.\n4. **Transport**: The signed data is sent via HTTP/2 to the Orchestrator.\n5. **Verification**: The receiver verifies the signature against the Trust Directory before processing.\n\n### Transaction Protocol (v0.1.7)\n\nThe SDK uses a **flat JSON structure** for transactions:\n\n```typescript\n{\n  service_id: \"srv_example_01\",\n  consumer_agent_id: \"auto-derived-sha256-hash\",\n  payload: { /* your data */ },\n  priority: \"normal\"\n}\n```\n\nThe signature is sent in the `X-Agent-Signature` header, not embedded in the payload.\n\n---\n\n## 🔧 Troubleshooting & FAQ\n\n**Q: I get a `AmorceAPIError` when transacting.**  \nA: Check the status code and response body in the error object. Common issues include invalid service IDs or missing API keys.\n\n**Q: I get `AmorceConfigError` about invalid URLs.**  \nA: Ensure your `DIRECTORY_URL` and `ORCHESTRATOR_URL` start with `http://` or `https://`.\n\n**Q: How do I get my Agent ID?**  \nA: Do not hardcode it. Access it via `identity.getAgentId()`. It is the SHA-256 hash of your public key.\n\n**Q: Does this work in the browser?**  \nA: Yes! The SDK is isomorphic and works in both Node.js and modern browsers. Make sure your build tool supports the required dependencies.\n\n**Q: How do I use environment variables in the browser?**  \nA: Use build tools like Webpack or Vite that support environment variable injection at build time.\n\n---\n\n## 📚 API Reference\n\n### `IdentityManager`\n\n#### Static Methods\n\n* `generate(): Promise<IdentityManager>` - Generates a new ephemeral identity.\n* `fromProvider(provider: IdentityProvider): Promise<IdentityManager>` - Loads identity from a provider.\n* `fromPrivateKey(privateKey: Uint8Array): Promise<IdentityManager>` - Loads from raw private key (legacy).\n* `verify(message, signatureBase64, publicKey): Promise<boolean>` - Verifies a signature.\n* `getCanonicalJsonBytes(payload): Uint8Array` - Returns canonical JSON bytes for signing.\n\n#### Instance Methods\n\n* `getPublicKeyPem(): string` - Returns public key in PEM format.\n* `getAgentId(): string` - Returns SHA-256 hash of public key (auto-derived agent ID).\n* `sign(message): Promise<string>` - Signs a message and returns base64 signature.\n* `toManifestJson(options): string` - **NEW v3.0.0** - Generates agent manifest JSON for registration.\n\n### `verifyRequest()` **NEW v3.0.0**\n\n```typescript\nverifyRequest(options: {\n  headers: Record<string, string>,\n  body: Buffer | string,\n  allowedIntents?: string[],\n  publicKey?: string,\n  directoryUrl?: string\n}): Promise<VerifiedRequest>\n```\n\nFor builders - verify incoming signed requests from other agents.\n\n### `MCPToolClient` **NEW v3.0.0**\n\n```typescript\n// Constructor\nnew MCPToolClient(identity: IdentityManager, wrapperUrl: string)\n\n// Methods\nlistTools(): Promise<MCPTool[]>  // Discover available tools\ncallTool(server: string, tool: string, args: any, approvalId?: string): Promise<any>\n```\n\n### `AmorceClient`\n\n#### Constructor\n\n```typescript\nnew AmorceClient(\n  identity: IdentityManager,\n  directoryUrl: string,\n  orchestratorUrl: string,\n  agentId?: string,  // Optional, auto-derived from identity if not provided\n  apiKey?: string    // Optional API key for orchestrator\n)\n```\n\n#### Methods\n\n* `discover(serviceType: string): Promise<ServiceContract[]>` - Discovers services from Trust Directory.\n* `transact(serviceContract, payload, priority?): Promise<any>` - Executes a transaction.\n* `requestApproval(options): Promise<string>` - **NEW v3.0.0** - Create HITL approval request.\n* `checkApproval(approvalId): Promise<ApprovalStatus>` - **NEW v3.0.0** - Check approval status.\n* `submitApproval(options): Promise<void>` - **NEW v3.0.0** - Submit approval decision.\n\n### Exception Classes\n\n* `AmorceError` - Base exception class\n* `AmorceConfigError` - Configuration errors\n* `AmorceNetworkError` - Network errors\n* `AmorceAPIError` - API errors (includes `statusCode` and `responseBody`)\n* `AmorceSecurityError` - Security/crypto errors\n* `AmorceValidationError` - Validation errors\n\n---\n\n## 🛠️ Development\n\nTo contribute to the SDK:\n\n```bash\n# Clone the repository\ngit clone https://github.com/trebortGolin/amorce-js-sdk.git\ncd amorce-js-sdk\n\n# Install dependencies\nnpm install\n\n# Build the SDK\nnpm run build\n\n# Run tests\nnpm test\n\n# Lint the code\nnpm run lint\n```\n\n---\n\n## 📄 License\n\nThis project is licensed under the MIT License.\n\n---\n\n## 🔗 Related Projects\n\n* [amorce_py_sdk](https://github.com/trebortGolin/amorce_py_sdk) - Python SDK for AATP\n* [amorce-trust-directory](https://github.com/trebortGolin/amorce-trust-directory) - Trust Directory service\n* [amorce-console](https://github.com/trebortGolin/amorce-console) - Management console\n\n---\n\n## 📝 Changelog\n\n### v3.1.0 (2025-12-15) 🆕\n\n**A2A Discovery: Make Your Agent Discoverable**\n\n* **[NEW]** `serveWellKnown()` - Express middleware to serve `/.well-known/agent.json`\n* **[NEW]** `createWellKnownHandler()` - Next.js App Router handler for A2A manifest\n* **[NEW]** `fetchManifest()` - Fetch A2A manifest from Amorce Directory\n* **[NEW]** `generateManifestJson()` - Generate static manifest JSON for deployment\n* **[ENHANCEMENT]** Aligned with Python SDK v0.2.2\n\n### v3.0.0 (2025-12-07)\n\n**MAJOR RELEASE - Full Feature Parity with Python SDK v0.2.1!**\n\n* **[NEW]** `verifyRequest()` - Verify incoming signed requests from other agents\n  - Auto-fetch public keys from Trust Directory\n  - Intent whitelisting for authorization\n  - Full Ed25519 signature verification\n  - For builders protecting their APIs\n\n* **[NEW]** HITL (Human-in-the-Loop) Support\n  - `requestApproval()` - Create approval requests\n  - `checkApproval()` - Check approval status\n  - `submitApproval()` - Submit approval decisions\n  - Timeout handling with auto-expiry\n  - Complete approval workflow\n\n* **[NEW]** MCP Integration\n  - `MCPToolClient` for secure tool calling\n  - `listTools()` - Discover 80+ MCP tools\n  - `callTool()` - Execute with cryptographic signatures\n  - Automatic HITL detection for write operations\n  - Production-ready with rate limiting\n\n* **[NEW]** `toManifestJson()` - Generate agent registration manifests\n  - Auto-populated agent_id and public_key\n  - Easy Trust Directory submission\n\n* **[ENHANCEMENT]** Updated documentation with comprehensive examples\n* **[ENHANCEMENT]** 15 new unit tests for all features\n* **[BREAKING]** Major version bump (v2.x → v3.x)\n* **[ALIGNED]** 100% feature parity with Python SDK v0.2.1\n\n---\n\n## 🌐 A2A Discovery: Make Your Agent Discoverable (NEW in v3.1.0)\n\n**Register your agent and instantly make it discoverable in the A2A ecosystem.**\n\n### Express Middleware\n\n```typescript\nimport express from 'express';\nimport { serveWellKnown } from '@amorce/sdk';\n\nconst app = express();\n\n// Add /.well-known/agent.json route with one line!\napp.use(serveWellKnown({ agentId: 'your-registered-agent-id' }));\n```\n\n### Next.js App Router\n\n```typescript\n// app/.well-known/agent.json/route.ts\nimport { createWellKnownHandler } from '@amorce/sdk';\n\nexport const GET = createWellKnownHandler({ agentId: 'your-agent-id' });\n```\n\n### Fetch Manifest Programmatically\n\n```typescript\nimport { fetchManifest } from '@amorce/sdk';\n\nconst manifest = await fetchManifest('your-agent-id');\nconsole.log(manifest);\n// {\n//   name: \"My Agent\",\n//   url: \"https://my-agent.com\",\n//   protocol_version: \"A2A/1.0\",\n//   authentication: { type: \"amorce\", public_key: \"...\" }\n// }\n```\n\n### Why A2A Discovery Matters\n\n- 🔍 **Discoverable** - Other agents can find and verify your agent\n- 🔐 **Trusted** - Public key distributed via trusted directory\n- 🔗 **Interoperable** - Works with Google A2A, MCP, and Amorce protocols\n\n---\n\n### v2.1.0 (2025-11-30)\n* **[FEATURE]** HTTP/2 support via `undici` for multiplexed connections and better performance\n* **[FEATURE]** Exponential backoff + jitter via `p-retry` (replaces basic `fetch-retry`)\n* **[FEATURE]** Auto-generated idempotency keys (UUIDv4) for transaction deduplication\n* **[FEATURE]** Structured `AmorceResponse` with `isSuccess()` and `isRetryable()` utility methods\n* **[FEATURE]** Additional headers: `X-Amorce-Idempotency`, `X-Amorce-Agent-ID`\n* **[ENHANCEMENT]** Feature parity with Python SDK v0.2.0\n* **[BREAKING]** Requires Node.js 18+ for optimal HTTP/2 support\n* **[DEPENDENCY]** Replaced `cross-fetch` with `undici`\n* **[DEPENDENCY]** Replaced `fetch-retry` with `p-retry`\n\n### v0.1.7 (2025-11-28)\n* **[BREAKING]** Updated transaction protocol to use flat JSON structure with signature in header\n* **[BREAKING]** Changed API key header from `X-ATP-Key` to `X-API-Key`\n* Added comprehensive exception hierarchy for better error handling\n* Added provider pattern for flexible identity management (`EnvVarProvider`)\n* Added auto-derived Agent ID (SHA-256 of public key)\n* Added `getCanonicalJsonBytes()` static utility\n* Improved URL validation in `AmorceClient` constructor\n* Enhanced documentation and examples\n\n### v0.1.2\n* Added Priority Lane support\n* Added automatic retry logic with exponential backoff\n* Fixed PEM encoding issues\n\n### v0.1.0\n* Initial release","readmeFilename":"README.md"}