@teneo-protocol/sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +14 -0
- package/.env.test.example +14 -0
- package/.eslintrc.json +26 -0
- package/.github/workflows/claude-code-review.yml +78 -0
- package/.github/workflows/claude-reviewer.yml +64 -0
- package/.github/workflows/publish-npm.yml +38 -0
- package/.github/workflows/push-to-main.yml +23 -0
- package/.node-version +1 -0
- package/.prettierrc +11 -0
- package/Dockerfile +25 -0
- package/LICENCE +661 -0
- package/README.md +709 -0
- package/dist/constants.d.ts +42 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +45 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/websocket-client.d.ts +261 -0
- package/dist/core/websocket-client.d.ts.map +1 -0
- package/dist/core/websocket-client.js +875 -0
- package/dist/core/websocket-client.js.map +1 -0
- package/dist/formatters/response-formatter.d.ts +354 -0
- package/dist/formatters/response-formatter.d.ts.map +1 -0
- package/dist/formatters/response-formatter.js +575 -0
- package/dist/formatters/response-formatter.js.map +1 -0
- package/dist/handlers/message-handler-registry.d.ts +155 -0
- package/dist/handlers/message-handler-registry.d.ts.map +1 -0
- package/dist/handlers/message-handler-registry.js +216 -0
- package/dist/handlers/message-handler-registry.js.map +1 -0
- package/dist/handlers/message-handlers/agent-selected-handler.d.ts +112 -0
- package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/agent-selected-handler.js +40 -0
- package/dist/handlers/message-handlers/agent-selected-handler.js.map +1 -0
- package/dist/handlers/message-handlers/agents-list-handler.d.ts +14 -0
- package/dist/handlers/message-handlers/agents-list-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/agents-list-handler.js +25 -0
- package/dist/handlers/message-handlers/agents-list-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-error-handler.d.ts +71 -0
- package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/auth-error-handler.js +30 -0
- package/dist/handlers/message-handlers/auth-error-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-message-handler.d.ts +18 -0
- package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/auth-message-handler.js +60 -0
- package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-required-handler.d.ts +76 -0
- package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/auth-required-handler.js +23 -0
- package/dist/handlers/message-handlers/auth-required-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-success-handler.d.ts +18 -0
- package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/auth-success-handler.js +51 -0
- package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -0
- package/dist/handlers/message-handlers/base-handler.d.ts +55 -0
- package/dist/handlers/message-handlers/base-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/base-handler.js +83 -0
- package/dist/handlers/message-handlers/base-handler.js.map +1 -0
- package/dist/handlers/message-handlers/challenge-handler.d.ts +73 -0
- package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/challenge-handler.js +47 -0
- package/dist/handlers/message-handlers/challenge-handler.js.map +1 -0
- package/dist/handlers/message-handlers/error-message-handler.d.ts +76 -0
- package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/error-message-handler.js +29 -0
- package/dist/handlers/message-handlers/error-message-handler.js.map +1 -0
- package/dist/handlers/message-handlers/index.d.ts +28 -0
- package/dist/handlers/message-handlers/index.d.ts.map +1 -0
- package/dist/handlers/message-handlers/index.js +100 -0
- package/dist/handlers/message-handlers/index.js.map +1 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +122 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.js +30 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/ping-pong-handler.d.ts +104 -0
- package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/ping-pong-handler.js +36 -0
- package/dist/handlers/message-handlers/ping-pong-handler.js.map +1 -0
- package/dist/handlers/message-handlers/regular-message-handler.d.ts +56 -0
- package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/regular-message-handler.js +59 -0
- package/dist/handlers/message-handlers/regular-message-handler.js.map +1 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +81 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.js +48 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/task-response-handler.d.ts +14 -0
- package/dist/handlers/message-handlers/task-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/task-response-handler.js +44 -0
- package/dist/handlers/message-handlers/task-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/types.d.ts +51 -0
- package/dist/handlers/message-handlers/types.d.ts.map +1 -0
- package/dist/handlers/message-handlers/types.js +7 -0
- package/dist/handlers/message-handlers/types.js.map +1 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +81 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.js +48 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.js.map +1 -0
- package/dist/handlers/webhook-handler.d.ts +202 -0
- package/dist/handlers/webhook-handler.d.ts.map +1 -0
- package/dist/handlers/webhook-handler.js +511 -0
- package/dist/handlers/webhook-handler.js.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +217 -0
- package/dist/index.js.map +1 -0
- package/dist/managers/agent-registry.d.ts +173 -0
- package/dist/managers/agent-registry.d.ts.map +1 -0
- package/dist/managers/agent-registry.js +310 -0
- package/dist/managers/agent-registry.js.map +1 -0
- package/dist/managers/connection-manager.d.ts +134 -0
- package/dist/managers/connection-manager.d.ts.map +1 -0
- package/dist/managers/connection-manager.js +176 -0
- package/dist/managers/connection-manager.js.map +1 -0
- package/dist/managers/index.d.ts +9 -0
- package/dist/managers/index.d.ts.map +1 -0
- package/dist/managers/index.js +16 -0
- package/dist/managers/index.js.map +1 -0
- package/dist/managers/message-router.d.ts +112 -0
- package/dist/managers/message-router.d.ts.map +1 -0
- package/dist/managers/message-router.js +260 -0
- package/dist/managers/message-router.js.map +1 -0
- package/dist/managers/room-manager.d.ts +165 -0
- package/dist/managers/room-manager.d.ts.map +1 -0
- package/dist/managers/room-manager.js +227 -0
- package/dist/managers/room-manager.js.map +1 -0
- package/dist/teneo-sdk.d.ts +703 -0
- package/dist/teneo-sdk.d.ts.map +1 -0
- package/dist/teneo-sdk.js +907 -0
- package/dist/teneo-sdk.js.map +1 -0
- package/dist/types/config.d.ts +1047 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +720 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/error-codes.d.ts +29 -0
- package/dist/types/error-codes.d.ts.map +1 -0
- package/dist/types/error-codes.js +41 -0
- package/dist/types/error-codes.js.map +1 -0
- package/dist/types/events.d.ts +616 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +261 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/health.d.ts +40 -0
- package/dist/types/health.d.ts.map +1 -0
- package/dist/types/health.js +6 -0
- package/dist/types/health.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +123 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/messages.d.ts +3734 -0
- package/dist/types/messages.d.ts.map +1 -0
- package/dist/types/messages.js +482 -0
- package/dist/types/messages.js.map +1 -0
- package/dist/types/validation.d.ts +81 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +115 -0
- package/dist/types/validation.js.map +1 -0
- package/dist/utils/bounded-queue.d.ts +127 -0
- package/dist/utils/bounded-queue.d.ts.map +1 -0
- package/dist/utils/bounded-queue.js +181 -0
- package/dist/utils/bounded-queue.js.map +1 -0
- package/dist/utils/circuit-breaker.d.ts +141 -0
- package/dist/utils/circuit-breaker.d.ts.map +1 -0
- package/dist/utils/circuit-breaker.js +215 -0
- package/dist/utils/circuit-breaker.js.map +1 -0
- package/dist/utils/deduplication-cache.d.ts +110 -0
- package/dist/utils/deduplication-cache.d.ts.map +1 -0
- package/dist/utils/deduplication-cache.js +177 -0
- package/dist/utils/deduplication-cache.js.map +1 -0
- package/dist/utils/event-waiter.d.ts +101 -0
- package/dist/utils/event-waiter.d.ts.map +1 -0
- package/dist/utils/event-waiter.js +118 -0
- package/dist/utils/event-waiter.js.map +1 -0
- package/dist/utils/index.d.ts +51 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +72 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +22 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +91 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +122 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +190 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/retry-policy.d.ts +191 -0
- package/dist/utils/retry-policy.d.ts.map +1 -0
- package/dist/utils/retry-policy.js +225 -0
- package/dist/utils/retry-policy.js.map +1 -0
- package/dist/utils/secure-private-key.d.ts +113 -0
- package/dist/utils/secure-private-key.d.ts.map +1 -0
- package/dist/utils/secure-private-key.js +188 -0
- package/dist/utils/secure-private-key.js.map +1 -0
- package/dist/utils/signature-verifier.d.ts +143 -0
- package/dist/utils/signature-verifier.d.ts.map +1 -0
- package/dist/utils/signature-verifier.js +238 -0
- package/dist/utils/signature-verifier.js.map +1 -0
- package/dist/utils/ssrf-validator.d.ts +36 -0
- package/dist/utils/ssrf-validator.d.ts.map +1 -0
- package/dist/utils/ssrf-validator.js +195 -0
- package/dist/utils/ssrf-validator.js.map +1 -0
- package/examples/.env.example +17 -0
- package/examples/basic-usage.ts +211 -0
- package/examples/production-dashboard/.env.example +153 -0
- package/examples/production-dashboard/package.json +39 -0
- package/examples/production-dashboard/public/dashboard.html +642 -0
- package/examples/production-dashboard/server.ts +753 -0
- package/examples/webhook-integration.ts +239 -0
- package/examples/x-influencer-battle-redesign.html +1065 -0
- package/examples/x-influencer-battle-server.ts +217 -0
- package/examples/x-influencer-battle.html +787 -0
- package/package.json +65 -0
- package/src/constants.ts +43 -0
- package/src/core/websocket-client.test.ts +512 -0
- package/src/core/websocket-client.ts +1056 -0
- package/src/formatters/response-formatter.test.ts +571 -0
- package/src/formatters/response-formatter.ts +677 -0
- package/src/handlers/message-handler-registry.ts +239 -0
- package/src/handlers/message-handlers/agent-selected-handler.ts +40 -0
- package/src/handlers/message-handlers/agents-list-handler.ts +26 -0
- package/src/handlers/message-handlers/auth-error-handler.ts +31 -0
- package/src/handlers/message-handlers/auth-message-handler.ts +66 -0
- package/src/handlers/message-handlers/auth-required-handler.ts +23 -0
- package/src/handlers/message-handlers/auth-success-handler.ts +57 -0
- package/src/handlers/message-handlers/base-handler.ts +101 -0
- package/src/handlers/message-handlers/challenge-handler.ts +57 -0
- package/src/handlers/message-handlers/error-message-handler.ts +27 -0
- package/src/handlers/message-handlers/index.ts +77 -0
- package/src/handlers/message-handlers/list-rooms-response-handler.ts +28 -0
- package/src/handlers/message-handlers/ping-pong-handler.ts +30 -0
- package/src/handlers/message-handlers/regular-message-handler.ts +65 -0
- package/src/handlers/message-handlers/subscribe-response-handler.ts +47 -0
- package/src/handlers/message-handlers/task-response-handler.ts +45 -0
- package/src/handlers/message-handlers/types.ts +77 -0
- package/src/handlers/message-handlers/unsubscribe-response-handler.ts +47 -0
- package/src/handlers/webhook-handler.test.ts +789 -0
- package/src/handlers/webhook-handler.ts +576 -0
- package/src/index.ts +269 -0
- package/src/managers/agent-registry.test.ts +466 -0
- package/src/managers/agent-registry.ts +347 -0
- package/src/managers/connection-manager.ts +195 -0
- package/src/managers/index.ts +9 -0
- package/src/managers/message-router.ts +349 -0
- package/src/managers/room-manager.ts +248 -0
- package/src/teneo-sdk.ts +1022 -0
- package/src/types/config.test.ts +325 -0
- package/src/types/config.ts +799 -0
- package/src/types/error-codes.ts +44 -0
- package/src/types/events.test.ts +302 -0
- package/src/types/events.ts +382 -0
- package/src/types/health.ts +46 -0
- package/src/types/index.ts +199 -0
- package/src/types/messages.test.ts +660 -0
- package/src/types/messages.ts +570 -0
- package/src/types/validation.ts +123 -0
- package/src/utils/bounded-queue.test.ts +356 -0
- package/src/utils/bounded-queue.ts +205 -0
- package/src/utils/circuit-breaker.test.ts +394 -0
- package/src/utils/circuit-breaker.ts +262 -0
- package/src/utils/deduplication-cache.test.ts +380 -0
- package/src/utils/deduplication-cache.ts +198 -0
- package/src/utils/event-waiter.test.ts +381 -0
- package/src/utils/event-waiter.ts +172 -0
- package/src/utils/index.ts +74 -0
- package/src/utils/logger.ts +87 -0
- package/src/utils/rate-limiter.test.ts +341 -0
- package/src/utils/rate-limiter.ts +211 -0
- package/src/utils/retry-policy.test.ts +558 -0
- package/src/utils/retry-policy.ts +272 -0
- package/src/utils/secure-private-key.test.ts +356 -0
- package/src/utils/secure-private-key.ts +205 -0
- package/src/utils/signature-verifier.test.ts +464 -0
- package/src/utils/signature-verifier.ts +298 -0
- package/src/utils/ssrf-validator.test.ts +372 -0
- package/src/utils/ssrf-validator.ts +224 -0
- package/tests/integration/real-server.test.ts +740 -0
- package/tests/integration/websocket.test.ts +381 -0
- package/tests/integration-setup.ts +16 -0
- package/tests/setup.ts +34 -0
- package/tsconfig.json +32 -0
- package/vitest.config.ts +42 -0
- package/vitest.integration.config.ts +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
# Teneo Protocol SDK
|
|
2
|
+
|
|
3
|
+
**Connect your app to the Teneo AI Agent Network**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@teneo-protocol/sdk)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
[](/)
|
|
9
|
+
|
|
10
|
+
The Teneo Protocol SDK lets you connect your application to a **decentralized network of specialized AI agents**. Instead of calling a single AI model, your app taps into an entire ecosystem where:
|
|
11
|
+
|
|
12
|
+
- ๐ค **Multiple AI agents** with different specializations handle your requests
|
|
13
|
+
- ๐ง **Intelligent routing** automatically selects the best agent for each query
|
|
14
|
+
- ๐ **Web3-native authentication** using Ethereum wallet signatures (no API keys!)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## ๐ Quickstart
|
|
19
|
+
|
|
20
|
+
### Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm install @teneo-protocol/sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Your First Connection (10 Lines)
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { TeneoSDK } from "@teneo-protocol/sdk";
|
|
30
|
+
|
|
31
|
+
// 1. Initialize with your Ethereum private key
|
|
32
|
+
const sdk = new TeneoSDK({
|
|
33
|
+
wsUrl: "wss://developer.chatroom.teneo-protocol.ai/ws",
|
|
34
|
+
privateKey: "your_private_key_here" // No 0x prefix
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// 2. Listen for responses
|
|
38
|
+
sdk.on("agent:response", (response) => {
|
|
39
|
+
console.log(`${response.agentName}: ${response.humanized}`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// 3. Connect and send a message
|
|
43
|
+
await sdk.connect();
|
|
44
|
+
await sdk.sendMessage("Give me the last 5 tweets from @elonmusk");
|
|
45
|
+
|
|
46
|
+
// The coordinator will select proper agent and return the results
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**That's it!** The coordinator automatically:
|
|
50
|
+
1. Routes your message to the right agent
|
|
51
|
+
2. Gets the response
|
|
52
|
+
3. Delivers it via the event you're listening to
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## How It Works
|
|
57
|
+
|
|
58
|
+
### 1. Agent Network Architecture
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Your App
|
|
62
|
+
โ
|
|
63
|
+
Teneo SDK (This library)
|
|
64
|
+
โ
|
|
65
|
+
WebSocket Connection
|
|
66
|
+
โ
|
|
67
|
+
Teneo Coordinator โโโ Selects best agent
|
|
68
|
+
โ
|
|
69
|
+
โโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโ
|
|
70
|
+
โ X โAnalyticsโ Reddit โ Custom โ
|
|
71
|
+
โ Agent โ Agent โ Agent โ Agents โ
|
|
72
|
+
โโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโ
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 3. Web3 Authentication
|
|
76
|
+
|
|
77
|
+
Unlike traditional APIs with API keys, Teneo uses **Ethereum wallet signatures**:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// Challenge-response authentication flow:
|
|
81
|
+
// 1. SDK connects to Teneo network
|
|
82
|
+
// 2. Server sends random challenge string
|
|
83
|
+
// 3. SDK signs: "Teneo authentication challenge: {challenge}"
|
|
84
|
+
// 4. Server verifies signature against your wallet address
|
|
85
|
+
// 5. โ
Authenticated! You can now send messages
|
|
86
|
+
|
|
87
|
+
// Your private key never leaves your machine
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This enables:
|
|
91
|
+
- ๐ **No API keys to manage** - Your wallet IS your identity
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## ๐ฏ Running the Examples
|
|
96
|
+
|
|
97
|
+
### Setup
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git clone https://github.com/TeneoProtocolAI/teneo-sdk.git
|
|
101
|
+
cd teneo-sdk
|
|
102
|
+
pnpm install
|
|
103
|
+
pnpm run build
|
|
104
|
+
|
|
105
|
+
# Set credentials
|
|
106
|
+
export PRIVATE_KEY=your_private_key
|
|
107
|
+
export TENEO_WS_URL=wss://developer.chatroom.teneo-protocol.ai/ws
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Basic Usage Example
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx ts-node examples/basic-usage.ts
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Demonstrates:
|
|
117
|
+
- โ
Connection and authentication
|
|
118
|
+
- โ
Agent discovery
|
|
119
|
+
- โ
Room management
|
|
120
|
+
- โ
Sending messages
|
|
121
|
+
- โ
Event listeners
|
|
122
|
+
- โ
Secure private key handling
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## ๐ Complete Examples
|
|
128
|
+
|
|
129
|
+
### Example 1: Request-Response Pattern
|
|
130
|
+
|
|
131
|
+
Wait for specific responses with timeout:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
const sdk = new TeneoSDK({
|
|
135
|
+
wsUrl: process.env.TENEO_WS_URL!,
|
|
136
|
+
privateKey: process.env.PRIVATE_KEY!
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
await sdk.connect();
|
|
140
|
+
|
|
141
|
+
// Wait for response (blocks until agent responds or timeout)
|
|
142
|
+
const response = await sdk.sendMessage(
|
|
143
|
+
"Give me the last 5 tweets from @elonmusk?",
|
|
144
|
+
{
|
|
145
|
+
waitForResponse: true,
|
|
146
|
+
timeout: 30000, // 30 seconds
|
|
147
|
+
format: "both" // Get both raw data and humanized text
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
console.log("Agent:", response.agentName);
|
|
152
|
+
console.log("Answer:", response.humanized);
|
|
153
|
+
console.log("Raw data:", response.raw);
|
|
154
|
+
|
|
155
|
+
// Output:
|
|
156
|
+
// Agent: X Agent
|
|
157
|
+
// Answer: Timeline for @elonmusk (5 tweets) ...
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Example 2: Multi-Room System
|
|
161
|
+
|
|
162
|
+
Organize agents by context using rooms:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const sdk = new TeneoSDK({
|
|
166
|
+
wsUrl: process.env.TENEO_WS_URL!,
|
|
167
|
+
privateKey: process.env.PRIVATE_KEY!,
|
|
168
|
+
autoJoinRooms: ["Crawler Room", "KOL tracker"]
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Each room may have different agents available
|
|
172
|
+
await sdk.connect();
|
|
173
|
+
|
|
174
|
+
// Send to specific room contexts
|
|
175
|
+
await sdk.sendMessage("Get latest tweets from @elonmusk", { room: "KOL tracker" });
|
|
176
|
+
// โ Routed to X Agent in KOL tracker room
|
|
177
|
+
|
|
178
|
+
await sdk.sendMessage("Crawl this website for data", { room: "Crawler Room" });
|
|
179
|
+
// โ Routed to Crawler Agent in Crawler Room
|
|
180
|
+
|
|
181
|
+
// Manage rooms dynamically
|
|
182
|
+
const rooms = sdk.getSubscribedRooms();
|
|
183
|
+
console.log("Active rooms:", rooms);
|
|
184
|
+
// Output: Active rooms: ['Crawler Room', 'KOL tracker']
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
### Example 3: Webhook Integration
|
|
189
|
+
|
|
190
|
+
Receive agent responses via HTTP POST to your server:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// Your webhook endpoint (Express)
|
|
194
|
+
import express from "express";
|
|
195
|
+
const app = express();
|
|
196
|
+
app.use(express.json());
|
|
197
|
+
|
|
198
|
+
app.post("/teneo-webhook", (req, res) => {
|
|
199
|
+
const { event, data, timestamp } = req.body;
|
|
200
|
+
|
|
201
|
+
if (event === "task_response") {
|
|
202
|
+
console.log(`Agent: ${data.agentName}`);
|
|
203
|
+
console.log(`Message: ${data.content}`);
|
|
204
|
+
|
|
205
|
+
// Save to your database
|
|
206
|
+
db.saveAgentResponse({
|
|
207
|
+
agentId: data.agentId,
|
|
208
|
+
content: data.content,
|
|
209
|
+
timestamp: new Date(timestamp)
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
res.sendStatus(200);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
app.listen(8080);
|
|
217
|
+
|
|
218
|
+
// Teneo SDK with webhook
|
|
219
|
+
const sdk = new TeneoSDK({
|
|
220
|
+
wsUrl: process.env.TENEO_WS_URL!,
|
|
221
|
+
privateKey: process.env.PRIVATE_KEY!,
|
|
222
|
+
webhookUrl: "https://your-webhook.com/",
|
|
223
|
+
webhookHeaders: {
|
|
224
|
+
"Authorization": "Bearer your-secret-token"
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Monitor webhook delivery
|
|
229
|
+
sdk.on("webhook:sent", () => console.log("๐ค Webhook sent"));
|
|
230
|
+
sdk.on("webhook:success", () => console.log("โ
Webhook delivered"));
|
|
231
|
+
sdk.on("webhook:error", (error) => {
|
|
232
|
+
console.error("โ Webhook failed:", error.message);
|
|
233
|
+
// Circuit breaker will automatically retry
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
await sdk.connect();
|
|
237
|
+
|
|
238
|
+
// Check webhook health
|
|
239
|
+
const status = sdk.getWebhookStatus();
|
|
240
|
+
console.log("Queue size:", status.queueSize);
|
|
241
|
+
console.log("Circuit state:", status.circuitState); // OPEN/CLOSED/HALF_OPEN
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## ๐จ Event System
|
|
247
|
+
|
|
248
|
+
The SDK is fully event-driven. Subscribe to what matters:
|
|
249
|
+
|
|
250
|
+
### Connection & Authentication
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
sdk.on("connection:open", () => console.log("๐ WebSocket connected"));
|
|
254
|
+
sdk.on("connection:close", (code, reason) => console.log(`โ Disconnected: ${reason}`));
|
|
255
|
+
sdk.on("connection:reconnecting", (attempt) => console.log(`๐ Reconnecting (attempt ${attempt})`));
|
|
256
|
+
|
|
257
|
+
sdk.on("auth:challenge", (challenge) => console.log("๐ Challenge received, signing with wallet..."));
|
|
258
|
+
sdk.on("auth:success", (state) => {
|
|
259
|
+
console.log(`โ
Authenticated as ${state.walletAddress}`);
|
|
260
|
+
console.log(`Whitelisted: ${state.isWhitelisted}`);
|
|
261
|
+
});
|
|
262
|
+
sdk.on("auth:error", (error) => console.error("โ Auth failed:", error.message));
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Agent Events
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
sdk.on("agent:selected", (selection) => {
|
|
269
|
+
console.log(`๐ค ${selection.agentName} was selected by coordinator`);
|
|
270
|
+
console.log(`Reasoning: ${selection.reasoning}`);
|
|
271
|
+
console.log(`Confidence: ${selection.confidence}`);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
sdk.on("agent:response", (response) => {
|
|
275
|
+
console.log(`๐ฌ ${response.agentName}: ${response.humanized}`);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
sdk.on("agent:list", (agents) => {
|
|
279
|
+
console.log(`๐ Agent list updated: ${agents.length} agents available`);
|
|
280
|
+
agents.forEach(agent => {
|
|
281
|
+
console.log(` - ${agent.name}: ${agent.capabilities?.join(", ")}`);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Room Events
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
sdk.on("room:subscribed", (data) => {
|
|
290
|
+
console.log(`โ
Joined room: ${data.roomId}`);
|
|
291
|
+
console.log(`All subscribed rooms: ${data.subscriptions.join(", ")}`);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
sdk.on("room:unsubscribed", (data) => {
|
|
295
|
+
console.log(`๐ Left room: ${data.roomId}`);
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## โ๏ธ Configuration
|
|
302
|
+
|
|
303
|
+
### Simple Configuration
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
const sdk = new TeneoSDK({
|
|
307
|
+
wsUrl: "wss://developer.chatroom.teneo-protocol.ai/ws",
|
|
308
|
+
privateKey: "your_key", // No 0x prefix
|
|
309
|
+
defaultRoom: "general",
|
|
310
|
+
reconnect: true,
|
|
311
|
+
logLevel: "info"
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Advanced Configuration (Builder Pattern)
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import { SDKConfigBuilder, SecurePrivateKey } from "@teneo-protocol/sdk";
|
|
319
|
+
|
|
320
|
+
// Encrypt private key in memory (AES-256-GCM)
|
|
321
|
+
const secureKey = new SecurePrivateKey(process.env.PRIVATE_KEY!);
|
|
322
|
+
|
|
323
|
+
const config = new SDKConfigBuilder()
|
|
324
|
+
// Required
|
|
325
|
+
.withWebSocketUrl("wss://developer.chatroom.teneo-protocol.ai/ws")
|
|
326
|
+
.withAuthentication(secureKey) // Encrypted key
|
|
327
|
+
|
|
328
|
+
// Rooms
|
|
329
|
+
.withRoom("general", ["announcements", "support"]) // default + auto-join
|
|
330
|
+
|
|
331
|
+
// Reconnection strategy
|
|
332
|
+
.withReconnectionStrategy({
|
|
333
|
+
type: "exponential",
|
|
334
|
+
baseDelay: 3000, // Start at 3 seconds
|
|
335
|
+
maxDelay: 120000, // Cap at 2 minutes
|
|
336
|
+
maxAttempts: 20,
|
|
337
|
+
jitter: true // Prevent thundering herd
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
// Webhook with retry
|
|
341
|
+
.withWebhook("https://your-server.com/webhook", {
|
|
342
|
+
"Authorization": "Bearer token"
|
|
343
|
+
})
|
|
344
|
+
.withWebhookRetryStrategy({
|
|
345
|
+
type: "exponential",
|
|
346
|
+
baseDelay: 1000,
|
|
347
|
+
maxDelay: 30000,
|
|
348
|
+
maxAttempts: 5
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
// Response formatting
|
|
352
|
+
.withResponseFormat({
|
|
353
|
+
format: "both", // 'raw' | 'humanized' | 'both'
|
|
354
|
+
includeMetadata: true
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
// Security
|
|
358
|
+
.withSignatureVerification({
|
|
359
|
+
enabled: true,
|
|
360
|
+
trustedAddresses: ["0xAgent1...", "0xAgent2..."],
|
|
361
|
+
requireFor: ["task_response"]
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
// Performance
|
|
365
|
+
.withRateLimit(10, 20) // 10 msg/sec, burst 20
|
|
366
|
+
.withMessageDeduplication(true, 60000, 10000)
|
|
367
|
+
.withLogging("debug")
|
|
368
|
+
|
|
369
|
+
.build();
|
|
370
|
+
|
|
371
|
+
const sdk = new TeneoSDK(config);
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Environment Variables
|
|
375
|
+
|
|
376
|
+
Create `.env`:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
TENEO_WS_URL=wss://developer.chatroom.teneo-protocol.ai/ws
|
|
380
|
+
PRIVATE_KEY=your_private_key_without_0x
|
|
381
|
+
WALLET_ADDRESS=0xYourWalletAddress
|
|
382
|
+
DEFAULT_ROOM=general
|
|
383
|
+
LOG_LEVEL=info
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Load them:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
import * as dotenv from "dotenv";
|
|
390
|
+
dotenv.config();
|
|
391
|
+
|
|
392
|
+
const sdk = new TeneoSDK({
|
|
393
|
+
wsUrl: process.env.TENEO_WS_URL!,
|
|
394
|
+
privateKey: process.env.PRIVATE_KEY!,
|
|
395
|
+
walletAddress: process.env.WALLET_ADDRESS,
|
|
396
|
+
defaultRoom: process.env.DEFAULT_ROOM,
|
|
397
|
+
logLevel: (process.env.LOG_LEVEL as any) || "info"
|
|
398
|
+
});
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## ๐ก๏ธ Production Features
|
|
404
|
+
|
|
405
|
+
### 1. Secure Private Key Management
|
|
406
|
+
|
|
407
|
+
Your Ethereum private key is **encrypted in memory** with AES-256-GCM:
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
import { SecurePrivateKey } from "@teneo-protocol/sdk";
|
|
411
|
+
|
|
412
|
+
// Immediately encrypted on construction
|
|
413
|
+
const secureKey = new SecurePrivateKey(process.env.PRIVATE_KEY!);
|
|
414
|
+
|
|
415
|
+
const sdk = new TeneoSDK({
|
|
416
|
+
wsUrl: "...",
|
|
417
|
+
privateKey: secureKey // Pass encrypted key
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// Key lifecycle:
|
|
421
|
+
// 1. Encrypted in memory with AES-256-GCM
|
|
422
|
+
// 2. Only decrypted temporarily during signing
|
|
423
|
+
// 3. Zeroed from memory immediately after use
|
|
424
|
+
// 4. Auto-cleanup on disconnect
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### 2. Circuit Breaker Pattern
|
|
428
|
+
|
|
429
|
+
Prevents cascading failures in webhook delivery:
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
const status = sdk.getWebhookStatus();
|
|
433
|
+
|
|
434
|
+
console.log("Circuit state:", status.circuitState);
|
|
435
|
+
// CLOSED = Normal operation, webhooks being delivered
|
|
436
|
+
// OPEN = Too many failures, failing fast (60s timeout)
|
|
437
|
+
// HALF_OPEN = Testing recovery (2 successes โ CLOSED)
|
|
438
|
+
|
|
439
|
+
// Circuit opens after 5 consecutive failures
|
|
440
|
+
// Automatically retries after 60 seconds
|
|
441
|
+
// Closes after 2 successful deliveries
|
|
442
|
+
|
|
443
|
+
// State transitions:
|
|
444
|
+
// CLOSED --[5 failures]--> OPEN --[60s]--> HALF_OPEN --[2 successes]--> CLOSED
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### 3. Retry Strategies
|
|
448
|
+
|
|
449
|
+
Configurable exponential backoff, linear, or constant delays:
|
|
450
|
+
|
|
451
|
+
| Strategy | Formula | Example (base=2s, mult=2) |
|
|
452
|
+
|----------|---------|---------------------------|
|
|
453
|
+
| **Exponential** | `base * mult^attempt` | 2s, 4s, 8s, 16s, 32s |
|
|
454
|
+
| **Linear** | `base * attempt` | 2s, 4s, 6s, 8s, 10s |
|
|
455
|
+
| **Constant** | `base` | 2s, 2s, 2s, 2s, 2s |
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
const config = new SDKConfigBuilder()
|
|
459
|
+
.withReconnectionStrategy({
|
|
460
|
+
type: "exponential",
|
|
461
|
+
baseDelay: 3000,
|
|
462
|
+
maxDelay: 120000,
|
|
463
|
+
maxAttempts: 20,
|
|
464
|
+
jitter: true // Add 0-1000ms randomness
|
|
465
|
+
})
|
|
466
|
+
.build();
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### 4. Message Deduplication
|
|
470
|
+
|
|
471
|
+
Prevents duplicate message processing with TTL-based cache:
|
|
472
|
+
|
|
473
|
+
```typescript
|
|
474
|
+
const config = new SDKConfigBuilder()
|
|
475
|
+
.withMessageDeduplication(
|
|
476
|
+
true, // Enable
|
|
477
|
+
300000, // 5 minute TTL
|
|
478
|
+
10000 // Cache up to 10k message IDs
|
|
479
|
+
)
|
|
480
|
+
.build();
|
|
481
|
+
|
|
482
|
+
// Duplicate messages are automatically filtered
|
|
483
|
+
// Useful for preventing replay attacks
|
|
484
|
+
// Auto-cleanup at 90% capacity
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### 6. Signature Verification
|
|
488
|
+
|
|
489
|
+
Verify agent messages are authentic:
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
const config = new SDKConfigBuilder()
|
|
493
|
+
.withSignatureVerification({
|
|
494
|
+
enabled: true,
|
|
495
|
+
trustedAddresses: ["0xAgent1...", "0xAgent2..."],
|
|
496
|
+
requireFor: ["task_response", "agent_selected"],
|
|
497
|
+
strictMode: false // Only reject types in requireFor
|
|
498
|
+
})
|
|
499
|
+
.build();
|
|
500
|
+
|
|
501
|
+
sdk.on("signature:verified", (type, address) => {
|
|
502
|
+
console.log(`โ
Verified ${type} from ${address}`);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
sdk.on("signature:failed", (type, reason) => {
|
|
506
|
+
console.warn(`โ ๏ธ Invalid signature on ${type}: ${reason}`);
|
|
507
|
+
});
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## ๐ Monitoring & Health
|
|
513
|
+
|
|
514
|
+
### Health Check
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
const health = sdk.getHealth();
|
|
518
|
+
|
|
519
|
+
console.log("Status:", health.status); // 'healthy' | 'degraded' | 'unhealthy'
|
|
520
|
+
console.log("Connected:", health.connection.connected);
|
|
521
|
+
console.log("Authenticated:", health.connection.authenticated);
|
|
522
|
+
console.log("Uptime:", health.uptime);
|
|
523
|
+
|
|
524
|
+
if (health.webhook) {
|
|
525
|
+
console.log("Webhook queue:", health.webhook.queueSize);
|
|
526
|
+
console.log("Circuit state:", health.webhook.circuitState);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (health.rateLimit) {
|
|
530
|
+
console.log("Available tokens:", health.rateLimit.availableTokens);
|
|
531
|
+
}
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Connection State
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
const state = sdk.getConnectionState();
|
|
538
|
+
|
|
539
|
+
console.log("Connected:", state.connected);
|
|
540
|
+
console.log("Authenticated:", state.authenticated);
|
|
541
|
+
console.log("Reconnecting:", state.reconnecting);
|
|
542
|
+
console.log("Reconnect attempts:", state.reconnectAttempts);
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Performance Metrics
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
// Rate limiter status
|
|
549
|
+
const rateLimit = sdk.getRateLimiterStatus();
|
|
550
|
+
if (rateLimit) {
|
|
551
|
+
console.log("Available:", rateLimit.availableTokens);
|
|
552
|
+
console.log("Rate:", rateLimit.tokensPerSecond, "/sec");
|
|
553
|
+
console.log("Burst capacity:", rateLimit.maxBurst);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Deduplication cache
|
|
557
|
+
const dedup = sdk.getDeduplicationStatus();
|
|
558
|
+
if (dedup) {
|
|
559
|
+
console.log("Cache size:", dedup.cacheSize);
|
|
560
|
+
console.log("Max size:", dedup.maxSize);
|
|
561
|
+
console.log("Usage:", Math.round((dedup.cacheSize / dedup.maxSize) * 100), "%");
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
---
|
|
566
|
+
|
|
567
|
+
## ๐ง Troubleshooting
|
|
568
|
+
|
|
569
|
+
### Issue: "ERR_REQUIRE_ESM" Error
|
|
570
|
+
|
|
571
|
+
**Problem:**
|
|
572
|
+
```
|
|
573
|
+
Error [ERR_REQUIRE_ESM]: require() of ES Module node-fetch not supported
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
**Solution:** Use the compiled version:
|
|
577
|
+
|
|
578
|
+
```bash
|
|
579
|
+
# โ
Correct
|
|
580
|
+
npm run build
|
|
581
|
+
node your-app.js
|
|
582
|
+
|
|
583
|
+
# โ Wrong
|
|
584
|
+
npx ts-node your-app.ts
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**Alternative:** Install node-fetch v2:
|
|
588
|
+
```bash
|
|
589
|
+
npm install node-fetch@2.7.0
|
|
590
|
+
npm run build
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### Issue: Authentication Failed
|
|
594
|
+
|
|
595
|
+
**Problem:** Can't authenticate with Teneo network.
|
|
596
|
+
|
|
597
|
+
**Solutions:**
|
|
598
|
+
|
|
599
|
+
1. **Check private key format (64 hex characters, no 0x):**
|
|
600
|
+
```typescript
|
|
601
|
+
// โ
Good
|
|
602
|
+
privateKey: "dafe885a73d87dc34b7933068423b40a646adf5cef45954265e9a1b9be6bad9d"
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
2. **Verify key length:**
|
|
606
|
+
```bash
|
|
607
|
+
echo -n "your_key" | wc -c
|
|
608
|
+
# Should output: 64
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
3. **Enable debug logging:**
|
|
612
|
+
```typescript
|
|
613
|
+
const sdk = new TeneoSDK({
|
|
614
|
+
wsUrl: "...",
|
|
615
|
+
privateKey: "...",
|
|
616
|
+
logLevel: "debug"
|
|
617
|
+
});
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Issue: Rate Limiting
|
|
621
|
+
|
|
622
|
+
**Problem:**
|
|
623
|
+
```
|
|
624
|
+
RateLimitError: Rate limit exceeded
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
**Solutions:**
|
|
628
|
+
|
|
629
|
+
1. **Slow down requests:**
|
|
630
|
+
```typescript
|
|
631
|
+
for (const message of messages) {
|
|
632
|
+
await sdk.sendMessage(message);
|
|
633
|
+
await new Promise(r => setTimeout(r, 200)); // 200ms delay
|
|
634
|
+
}
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Issue: Webhook Failures
|
|
638
|
+
|
|
639
|
+
**Solutions:**
|
|
640
|
+
|
|
641
|
+
1. **Verify HTTPS (except localhost):**
|
|
642
|
+
```typescript
|
|
643
|
+
// โ
Good
|
|
644
|
+
webhookUrl: "https://your-server.com/webhook"
|
|
645
|
+
webhookUrl: "http://localhost:3000/webhook"
|
|
646
|
+
|
|
647
|
+
// โ Bad
|
|
648
|
+
webhookUrl: "http://your-server.com/webhook"
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
2. **Test manually:**
|
|
652
|
+
```bash
|
|
653
|
+
curl -X POST https://your-server.com/webhook \
|
|
654
|
+
-H "Content-Type: application/json" \
|
|
655
|
+
-d '{"test": true}'
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
3. **Check circuit breaker:**
|
|
659
|
+
```typescript
|
|
660
|
+
const status = sdk.getWebhookStatus();
|
|
661
|
+
if (status.circuitState === "OPEN") {
|
|
662
|
+
console.log("Circuit open, will retry in 60s");
|
|
663
|
+
}
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## ๐งช Testing
|
|
669
|
+
|
|
670
|
+
```bash
|
|
671
|
+
npm test # All tests
|
|
672
|
+
npm run test:watch # Watch mode
|
|
673
|
+
npm run test:coverage # Coverage report
|
|
674
|
+
npm run test:unit # Unit tests only
|
|
675
|
+
npm run test:integration # Integration tests
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
**Test Results:**
|
|
679
|
+
- โ
488 unit tests passing
|
|
680
|
+
- โ
98.6% pass rate
|
|
681
|
+
- โ
Comprehensive coverage
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## ๐ค Contributing
|
|
686
|
+
|
|
687
|
+
We welcome contributions!
|
|
688
|
+
|
|
689
|
+
1. Fork the repository
|
|
690
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
691
|
+
3. Make your changes
|
|
692
|
+
4. Add tests
|
|
693
|
+
5. Run `npm test`
|
|
694
|
+
6. Commit (`git commit -m 'Add amazing feature'`)
|
|
695
|
+
7. Push (`git push origin feature/amazing-feature`)
|
|
696
|
+
8. Open a Pull Request
|
|
697
|
+
|
|
698
|
+
---
|
|
699
|
+
|
|
700
|
+
## ๐ License
|
|
701
|
+
|
|
702
|
+
AGPL-3.0 License
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
<div align="center">
|
|
706
|
+
|
|
707
|
+
**Built with โค๏ธ by the [Teneo Team](https://teneo.pro)**
|
|
708
|
+
|
|
709
|
+
</div>
|