@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature-verifier.js","sourceRoot":"","sources":["../../src/utils/signature-verifier.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+BAAgE;AAqChE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAa,iBAAiB;IAG5B;;;;;;;;;;;;;OAaG;IACH,YAAY,UAAwC,EAAE;QACpD,IAAI,CAAC,OAAO,GAAG;YACb,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,EAAE;YAChD,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,IAAI,EAAE;YACxD,UAAU,EAAE,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK;SAC1E,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACI,KAAK,CAAC,MAAM,CAAC,OAAoB;QACtC,gCAAgC;QAChC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YACvB,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAE1D,OAAO;gBACL,KAAK,EAAE,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU;gBAC9C,gBAAgB,EAAE,IAAI;gBACtB,MAAM,EAAE,UAAU;oBAChB,CAAC,CAAC,wCAAwC,OAAO,CAAC,IAAI,GAAG;oBACzD,CAAC,CAAC,oCAAoC;aACzC,CAAC;QACJ,CAAC;QAED,qEAAqE;QACrE,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAEzD,gCAAgC;QAChC,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;QAE5D,IAAI,CAAC;YACH,4CAA4C;YAC5C,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAEnE,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,OAAO;oBACL,KAAK,EAAE,KAAK;oBACZ,gBAAgB,EAAE,KAAK;oBACvB,MAAM,EAAE,2EAA2E;iBACpF,CAAC;YACJ,CAAC;YAED,8BAA8B;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,oBAAa,EAAC;gBAClC,OAAO,EAAE,eAAe;gBACxB,OAAO,EAAE,WAAW;gBACpB,SAAS,EAAE,OAAO,CAAC,SAA0B;aAC9C,CAAC,CAAC;YAEH,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO;oBACL,KAAK,EAAE,KAAK;oBACZ,gBAAgB,EAAE,eAAe;oBACjC,gBAAgB,EAAE,KAAK;oBACvB,MAAM,EAAE,0EAA0E;iBACnF,CAAC;YACJ,CAAC;YAED,wDAAwD;YACxD,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;YAEzD,gEAAgE;YAChE,IAAI,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC3D,OAAO;oBACL,KAAK,EAAE,KAAK;oBACZ,gBAAgB,EAAE,eAAe;oBACjC,gBAAgB,EAAE,KAAK;oBACvB,SAAS,EAAE,KAAK;oBAChB,MAAM,EAAE,WAAW,eAAe,8BAA8B;iBACjE,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,KAAK,EAAE,IAAI;gBACX,gBAAgB,EAAE,eAAe;gBACjC,gBAAgB,EAAE,KAAK;gBACvB,SAAS;aACV,CAAC;QAEJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,gBAAgB,EAAE,KAAK;gBACvB,MAAM,EAAE,iCAAiC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;aAClG,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,iBAAiB,CAAC,OAAe;QACtC,6DAA6D;QAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAEvE,yDAAyD;QACzD,OAAO,IAAA,kBAAW,EAAC,SAAS,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;OAMG;IACI,kBAAkB,CAAC,OAAoB;QAC5C,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;QAEjE,qDAAqD;QACrD,MAAM,QAAQ,GAAwB,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YAC3D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;OAKG;IACI,mBAAmB,CAAC,WAAwB;QACjD,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjE,CAAC;IAED;;;;;OAKG;IACI,gBAAgB,CAAC,OAAgB;QACtC,IAAI,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC,CAAC,2BAA2B;QAC1C,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CACvC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAC3D,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,sBAAsB,CAAC,OAAoB;QACvD,wDAAwD;QACxD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,kDAAkD;YAClD,iEAAiE;YACjE,uDAAuD;YACvD,OAAO,OAAO,CAAC,SAAoB,CAAC;QACtC,CAAC;QAED,wDAAwD;QACxD,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YAChF,OAAO,OAAO,CAAC,IAAe,CAAC;QACjC,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,aAAa,CAAC,OAA8C;QACjE,IAAI,OAAO,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YAC3C,IAAI,CAAC,OAAO,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;QAC3D,CAAC;QACD,IAAI,OAAO,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;YAC/C,IAAI,CAAC,OAAO,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;QACnE,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACrC,IAAI,CAAC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QAC/C,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,UAAU;QACf,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;CACF;AA7OD,8CA6OC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSRF (Server-Side Request Forgery) Validator
|
|
3
|
+
* Prevents webhook URLs from pointing to internal/private network resources
|
|
4
|
+
*
|
|
5
|
+
* This utility blocks:
|
|
6
|
+
* - Private IP ranges (RFC1918: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
|
|
7
|
+
* - Loopback addresses (127.0.0.0/8, ::1)
|
|
8
|
+
* - Link-local addresses (169.254.0.0/16, fe80::/10)
|
|
9
|
+
* - Cloud metadata endpoints (AWS, GCP, Azure, DigitalOcean)
|
|
10
|
+
* - IPv6 private ranges (fc00::/7, fd00::/8)
|
|
11
|
+
* - Multicast and broadcast addresses
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Check if an IP address is in a private range
|
|
15
|
+
* Supports both IPv4 and IPv6
|
|
16
|
+
*/
|
|
17
|
+
export declare function isPrivateIP(hostname: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Check if a hostname is a blocked cloud metadata endpoint
|
|
20
|
+
*/
|
|
21
|
+
export declare function isCloudMetadataEndpoint(hostname: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a hostname is an allowed localhost exception
|
|
24
|
+
* Only true localhost addresses, not bind-all addresses
|
|
25
|
+
*/
|
|
26
|
+
export declare function isLocalhostException(hostname: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Validate a webhook URL for SSRF vulnerabilities
|
|
29
|
+
* Throws an error if the URL is unsafe
|
|
30
|
+
*
|
|
31
|
+
* @param url - The webhook URL to validate
|
|
32
|
+
* @param allowLocalhost - Whether to allow localhost URLs (for development)
|
|
33
|
+
* @throws Error if URL is unsafe or invalid
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateWebhookUrl(url: string, allowLocalhost?: boolean): void;
|
|
36
|
+
//# sourceMappingURL=ssrf-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssrf-validator.d.ts","sourceRoot":"","sources":["../../src/utils/ssrf-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAyCH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAqCrD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOjE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI9D;AAkBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,GAAE,OAAe,GAAG,IAAI,CAkFrF"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SSRF (Server-Side Request Forgery) Validator
|
|
4
|
+
* Prevents webhook URLs from pointing to internal/private network resources
|
|
5
|
+
*
|
|
6
|
+
* This utility blocks:
|
|
7
|
+
* - Private IP ranges (RFC1918: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
|
|
8
|
+
* - Loopback addresses (127.0.0.0/8, ::1)
|
|
9
|
+
* - Link-local addresses (169.254.0.0/16, fe80::/10)
|
|
10
|
+
* - Cloud metadata endpoints (AWS, GCP, Azure, DigitalOcean)
|
|
11
|
+
* - IPv6 private ranges (fc00::/7, fd00::/8)
|
|
12
|
+
* - Multicast and broadcast addresses
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.isPrivateIP = isPrivateIP;
|
|
16
|
+
exports.isCloudMetadataEndpoint = isCloudMetadataEndpoint;
|
|
17
|
+
exports.isLocalhostException = isLocalhostException;
|
|
18
|
+
exports.validateWebhookUrl = validateWebhookUrl;
|
|
19
|
+
const url_1 = require("url");
|
|
20
|
+
/**
|
|
21
|
+
* Blocked hostnames that should never be accessible via webhooks
|
|
22
|
+
* Includes cloud provider metadata endpoints and localhost variations
|
|
23
|
+
*/
|
|
24
|
+
const BLOCKED_HOSTNAMES = [
|
|
25
|
+
// AWS metadata endpoints
|
|
26
|
+
"169.254.169.254",
|
|
27
|
+
"fd00:ec2::254",
|
|
28
|
+
"instance-data",
|
|
29
|
+
"instance-data.ec2.internal",
|
|
30
|
+
// Google Cloud metadata
|
|
31
|
+
"metadata.google.internal",
|
|
32
|
+
"metadata.google.com",
|
|
33
|
+
// Azure metadata
|
|
34
|
+
"169.254.169.254", // Same as AWS
|
|
35
|
+
// DigitalOcean metadata
|
|
36
|
+
"169.254.169.254", // Same as AWS/Azure
|
|
37
|
+
// Kubernetes metadata
|
|
38
|
+
"kubernetes.default",
|
|
39
|
+
"kubernetes.default.svc",
|
|
40
|
+
"kubernetes.default.svc.cluster.local",
|
|
41
|
+
// Localhost bind-all (not safe for webhooks)
|
|
42
|
+
"0.0.0.0",
|
|
43
|
+
"[::]",
|
|
44
|
+
"::"
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Localhost hostnames that are allowed for development
|
|
48
|
+
*/
|
|
49
|
+
const LOCALHOST_HOSTNAMES = ["localhost", "127.0.0.1", "::1", "[::1]"];
|
|
50
|
+
/**
|
|
51
|
+
* Check if an IP address is in a private range
|
|
52
|
+
* Supports both IPv4 and IPv6
|
|
53
|
+
*/
|
|
54
|
+
function isPrivateIP(hostname) {
|
|
55
|
+
// Remove IPv6 brackets if present
|
|
56
|
+
const cleanHostname = hostname.replace(/^\[|\]$/g, "");
|
|
57
|
+
// IPv4 private ranges (RFC1918)
|
|
58
|
+
if (/^10\./.test(cleanHostname))
|
|
59
|
+
return true;
|
|
60
|
+
if (/^192\.168\./.test(cleanHostname))
|
|
61
|
+
return true;
|
|
62
|
+
if (/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(cleanHostname))
|
|
63
|
+
return true; // 172.16-31
|
|
64
|
+
// IPv4 loopback (127.0.0.0/8)
|
|
65
|
+
if (/^127\./.test(cleanHostname))
|
|
66
|
+
return true;
|
|
67
|
+
// IPv4 link-local (169.254.0.0/16)
|
|
68
|
+
if (/^169\.254\./.test(cleanHostname))
|
|
69
|
+
return true;
|
|
70
|
+
// IPv4 multicast (224.0.0.0/4)
|
|
71
|
+
if (/^2(2[4-9]|3[0-9])\./.test(cleanHostname))
|
|
72
|
+
return true;
|
|
73
|
+
// IPv4 broadcast
|
|
74
|
+
if (cleanHostname === "255.255.255.255")
|
|
75
|
+
return true;
|
|
76
|
+
// IPv6 private ranges
|
|
77
|
+
// Link-local (fe80::/10)
|
|
78
|
+
if (/^fe[89ab][0-9a-f]:/i.test(cleanHostname))
|
|
79
|
+
return true;
|
|
80
|
+
// Unique local addresses (fc00::/7)
|
|
81
|
+
if (/^f[cd][0-9a-f]{2}:/i.test(cleanHostname))
|
|
82
|
+
return true;
|
|
83
|
+
// IPv6 loopback (::1)
|
|
84
|
+
if (cleanHostname === "::1")
|
|
85
|
+
return true;
|
|
86
|
+
if (cleanHostname === "0:0:0:0:0:0:0:1")
|
|
87
|
+
return true;
|
|
88
|
+
// IPv6 unspecified (::)
|
|
89
|
+
if (cleanHostname === "::")
|
|
90
|
+
return true;
|
|
91
|
+
if (cleanHostname === "0:0:0:0:0:0:0:0")
|
|
92
|
+
return true;
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if a hostname is a blocked cloud metadata endpoint
|
|
97
|
+
*/
|
|
98
|
+
function isCloudMetadataEndpoint(hostname) {
|
|
99
|
+
const cleanHostname = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
100
|
+
return BLOCKED_HOSTNAMES.some((blocked) => cleanHostname === blocked.toLowerCase() || cleanHostname.endsWith(`.${blocked.toLowerCase()}`));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if a hostname is an allowed localhost exception
|
|
104
|
+
* Only true localhost addresses, not bind-all addresses
|
|
105
|
+
*/
|
|
106
|
+
function isLocalhostException(hostname) {
|
|
107
|
+
const cleanHostname = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
108
|
+
return LOCALHOST_HOSTNAMES.some((allowed) => cleanHostname === allowed.toLowerCase());
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check if hostname resolves to a Kubernetes service
|
|
112
|
+
* Blocks internal k8s service discovery
|
|
113
|
+
*/
|
|
114
|
+
function isKubernetesService(hostname) {
|
|
115
|
+
const cleanHostname = hostname.toLowerCase();
|
|
116
|
+
// Block .svc, .svc.cluster, .svc.cluster.local
|
|
117
|
+
if (cleanHostname.includes(".svc"))
|
|
118
|
+
return true;
|
|
119
|
+
// Block direct kubernetes service names
|
|
120
|
+
if (cleanHostname.startsWith("kubernetes"))
|
|
121
|
+
return true;
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Validate a webhook URL for SSRF vulnerabilities
|
|
126
|
+
* Throws an error if the URL is unsafe
|
|
127
|
+
*
|
|
128
|
+
* @param url - The webhook URL to validate
|
|
129
|
+
* @param allowLocalhost - Whether to allow localhost URLs (for development)
|
|
130
|
+
* @throws Error if URL is unsafe or invalid
|
|
131
|
+
*/
|
|
132
|
+
function validateWebhookUrl(url, allowLocalhost = false) {
|
|
133
|
+
let parsed;
|
|
134
|
+
try {
|
|
135
|
+
parsed = new url_1.URL(url);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
throw new Error(`Invalid webhook URL: ${error.message}`);
|
|
139
|
+
}
|
|
140
|
+
const hostname = parsed.hostname;
|
|
141
|
+
// Check protocol first (basic validation)
|
|
142
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
143
|
+
throw new Error(`Webhook URL must use HTTP or HTTPS protocol (got: ${parsed.protocol})`);
|
|
144
|
+
}
|
|
145
|
+
// Block cloud metadata endpoints FIRST (before any other checks)
|
|
146
|
+
if (isCloudMetadataEndpoint(hostname)) {
|
|
147
|
+
throw new Error(`Webhook URL blocked for security: ${hostname} is a cloud metadata endpoint. ` +
|
|
148
|
+
"This could expose sensitive credentials and secrets.");
|
|
149
|
+
}
|
|
150
|
+
// Block Kubernetes services
|
|
151
|
+
if (isKubernetesService(hostname)) {
|
|
152
|
+
throw new Error(`Webhook URL blocked for security: ${hostname} appears to be a Kubernetes service. ` +
|
|
153
|
+
"Internal service discovery is not allowed for webhooks.");
|
|
154
|
+
}
|
|
155
|
+
// Check localhost BEFORE private IP check (localhost is specific case of private IP)
|
|
156
|
+
if (isLocalhostException(hostname)) {
|
|
157
|
+
if (allowLocalhost) {
|
|
158
|
+
return; // Localhost is allowed for development
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
throw new Error(`Webhook URL blocked: ${hostname} is a localhost address. ` +
|
|
162
|
+
"Set allowInsecureWebhooks=true to allow localhost webhooks for testing.");
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Block private IP ranges
|
|
166
|
+
if (isPrivateIP(hostname)) {
|
|
167
|
+
throw new Error(`Webhook URL blocked for security: ${hostname} is a private IP address. ` +
|
|
168
|
+
"Webhooks cannot point to internal network resources. " +
|
|
169
|
+
"Use a publicly accessible endpoint or set allowInsecureWebhooks=true for testing.");
|
|
170
|
+
}
|
|
171
|
+
// For non-HTTPS, only allow localhost (which already passed checks above)
|
|
172
|
+
if (parsed.protocol === "http:") {
|
|
173
|
+
throw new Error("Webhook URL must use HTTPS for non-localhost endpoints. " +
|
|
174
|
+
"Use HTTPS or set allowInsecureWebhooks=true for testing with localhost.");
|
|
175
|
+
}
|
|
176
|
+
// Additional safety: block ports that are commonly internal
|
|
177
|
+
if (parsed.port) {
|
|
178
|
+
const port = parseInt(parsed.port, 10);
|
|
179
|
+
const dangerousPorts = [
|
|
180
|
+
22, // SSH
|
|
181
|
+
23, // Telnet
|
|
182
|
+
25, // SMTP
|
|
183
|
+
3306, // MySQL
|
|
184
|
+
5432, // PostgreSQL
|
|
185
|
+
6379, // Redis
|
|
186
|
+
9200, // Elasticsearch
|
|
187
|
+
27017 // MongoDB
|
|
188
|
+
];
|
|
189
|
+
if (dangerousPorts.includes(port)) {
|
|
190
|
+
throw new Error(`Webhook URL blocked for security: Port ${port} is commonly used for internal services. ` +
|
|
191
|
+
"Use a different port or set allowInsecureWebhooks=true for testing.");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=ssrf-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssrf-validator.js","sourceRoot":"","sources":["../../src/utils/ssrf-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Teneo SDK Examples - Environment Configuration
|
|
2
|
+
# Copy this file to .env and fill in your actual values
|
|
3
|
+
|
|
4
|
+
# Required: WebSocket URL for Teneo network
|
|
5
|
+
WS_URL=wss://developer.chatroom.teneo-protocol.ai/ws
|
|
6
|
+
|
|
7
|
+
# Required: Your Ethereum private key (keep this secret!)
|
|
8
|
+
PRIVATE_KEY=your-private-key-here
|
|
9
|
+
|
|
10
|
+
# Optional: Your wallet address (auto-derived from private key if not provided)
|
|
11
|
+
WALLET_ADDRESS=0x...
|
|
12
|
+
|
|
13
|
+
# Optional: Default room to join on connection
|
|
14
|
+
DEFAULT_ROOM=general
|
|
15
|
+
|
|
16
|
+
# Optional: Additional room ID (for multi-room examples)
|
|
17
|
+
ROOM_ID=your-room-id-here
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic usage example for Teneo Protocol SDK
|
|
3
|
+
* Demonstrates connection, authentication, and sending messages to agents
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { TeneoSDK, SDKConfigBuilder, SecurePrivateKey } from "../src";
|
|
7
|
+
|
|
8
|
+
// Load configuration from environment variables
|
|
9
|
+
const WS_URL =
|
|
10
|
+
process.env.WS_URL;
|
|
11
|
+
const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
|
|
12
|
+
const WALLET_ADDRESS = process.env.WALLET_ADDRESS;
|
|
13
|
+
const DEFAULT_ROOM = process.env.DEFAULT_ROOM || "general";
|
|
14
|
+
|
|
15
|
+
async function main() {
|
|
16
|
+
// Validate required configuration
|
|
17
|
+
if (!PRIVATE_KEY) {
|
|
18
|
+
console.error("ERROR: PRIVATE_KEY environment variable is required");
|
|
19
|
+
console.error("Set it with: export PRIVATE_KEY='your-private-key'");
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// SEC-3: Encrypt private key in memory for enhanced security
|
|
24
|
+
const secureKey = new SecurePrivateKey(PRIVATE_KEY);
|
|
25
|
+
console.log("✓ Private key encrypted in memory (SEC-3)");
|
|
26
|
+
|
|
27
|
+
// Build configuration using fluent API
|
|
28
|
+
const config = new SDKConfigBuilder()
|
|
29
|
+
.withWebSocketUrl(WS_URL)
|
|
30
|
+
.withAuthentication(secureKey, WALLET_ADDRESS) // Use encrypted key
|
|
31
|
+
.withAutoJoinRooms([DEFAULT_ROOM]) // Auto-join default room on connect
|
|
32
|
+
.withReconnection({ enabled: true, delay: 5000, maxAttempts: 10 }) // Enable reconnection
|
|
33
|
+
.withResponseFormat({ format: "both", includeMetadata: true }) // Get both raw and humanized responses with metadata
|
|
34
|
+
.withLogging("debug") // Enable debug logging
|
|
35
|
+
.build();
|
|
36
|
+
|
|
37
|
+
// Create SDK instance
|
|
38
|
+
const sdk = new TeneoSDK(config);
|
|
39
|
+
|
|
40
|
+
// Set up event listeners
|
|
41
|
+
setupEventListeners(sdk);
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
// Connect to Teneo network
|
|
45
|
+
console.log("\n→ Connecting to Teneo network...");
|
|
46
|
+
await sdk.connect();
|
|
47
|
+
console.log("✓ SDK is connected and authenticated!");
|
|
48
|
+
|
|
49
|
+
// Show current subscriptions
|
|
50
|
+
const subscribed = sdk.getSubscribedRooms();
|
|
51
|
+
console.log(
|
|
52
|
+
`\n→ Currently subscribed to ${subscribed.length} room(s): ${subscribed.join(", ")}`
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// Subscribe to additional room if available
|
|
56
|
+
const rooms = sdk.getRooms();
|
|
57
|
+
if (rooms.length > 1) {
|
|
58
|
+
const additionalRoom = rooms.find((r) => r.id !== DEFAULT_ROOM);
|
|
59
|
+
if (additionalRoom) {
|
|
60
|
+
console.log(
|
|
61
|
+
`\n→ Subscribing to additional room: ${additionalRoom.name || additionalRoom.id}`
|
|
62
|
+
);
|
|
63
|
+
await sdk.subscribeToRoom(additionalRoom.id);
|
|
64
|
+
|
|
65
|
+
// Show updated subscriptions
|
|
66
|
+
const updatedSubscriptions = sdk.getSubscribedRooms();
|
|
67
|
+
console.log(`✓ Now subscribed to: ${updatedSubscriptions.join(", ")}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Get list of available agents
|
|
72
|
+
const agents = sdk.getAgents();
|
|
73
|
+
console.log(`\n→ Available agents: ${agents.length}`);
|
|
74
|
+
agents.forEach((agent) => {
|
|
75
|
+
console.log(` • ${agent.name}: ${agent.description || "No description"}`);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// PERF-3: Demonstrate indexed agent lookups (O(1) complexity)
|
|
79
|
+
console.log("\n→ Testing indexed agent lookups (PERF-3):");
|
|
80
|
+
|
|
81
|
+
// Search by capability (O(1))
|
|
82
|
+
const weatherAgents = sdk.findAgentsByCapability("weather-forecast");
|
|
83
|
+
if (weatherAgents.length > 0) {
|
|
84
|
+
console.log(` ✓ Found ${weatherAgents.length} agent(s) with weather capability`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Search by name (O(k) where k = tokens)
|
|
88
|
+
const searchResults = sdk.findAgentsByName("agent");
|
|
89
|
+
if (searchResults.length > 0) {
|
|
90
|
+
console.log(` ✓ Found ${searchResults.length} agent(s) matching name search`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Search by status (O(1))
|
|
94
|
+
const onlineAgents = sdk.findAgentsByStatus("online");
|
|
95
|
+
console.log(` ✓ ${onlineAgents.length} agent(s) currently online`);
|
|
96
|
+
|
|
97
|
+
// Send message to the room
|
|
98
|
+
console.log("\n→ Sending message to room...");
|
|
99
|
+
const response = await sdk.sendMessage("Hello from the Teneo SDK!", {
|
|
100
|
+
room: DEFAULT_ROOM,
|
|
101
|
+
waitForResponse: true,
|
|
102
|
+
timeout: 30000
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (response && response.humanized) {
|
|
106
|
+
console.log("✓ Response received:", response.humanized.substring(0, 200));
|
|
107
|
+
} else if (response) {
|
|
108
|
+
console.log("✓ Response received (no humanized content)");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Wait for some messages
|
|
112
|
+
console.log("\n→ Listening for messages (press Ctrl+C to exit)...");
|
|
113
|
+
console.log(" Watch the event logs above for real-time updates");
|
|
114
|
+
await new Promise((resolve) => setTimeout(resolve, 60000));
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error("\n✗ Error:", error);
|
|
117
|
+
} finally {
|
|
118
|
+
// Clean up
|
|
119
|
+
console.log("\n→ Disconnecting...");
|
|
120
|
+
sdk.disconnect();
|
|
121
|
+
sdk.destroy();
|
|
122
|
+
console.log("✓ Cleanup complete");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function setupEventListeners(sdk: TeneoSDK) {
|
|
127
|
+
// Connection events
|
|
128
|
+
sdk.on("connection:open", () => {
|
|
129
|
+
console.log("[CONNECTION] Connected to WebSocket");
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
sdk.on("connection:close", (code, reason) => {
|
|
133
|
+
console.log(`[CONNECTION] Disconnected: ${code} - ${reason}`);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
sdk.on("connection:reconnecting", (attempt) => {
|
|
137
|
+
console.log(`[CONNECTION] Reconnecting... (attempt ${attempt})`);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
sdk.on("connection:reconnected", () => {
|
|
141
|
+
console.log("[CONNECTION] Reconnected successfully");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Authentication events
|
|
145
|
+
sdk.on("auth:challenge", (challenge) => {
|
|
146
|
+
console.log(`[AUTH] Authentication challenge received: ${challenge.substring(0, 10)}...`);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
sdk.on("auth:success", (state) => {
|
|
150
|
+
console.log(`[AUTH] Authenticated as: ${state.walletAddress}`);
|
|
151
|
+
console.log(`[AUTH] Whitelisted: ${state.isWhitelisted}`);
|
|
152
|
+
console.log(`[AUTH] Rooms: ${state.rooms?.join(", ") || "None"}`);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
sdk.on("auth:error", (error) => {
|
|
156
|
+
console.log(`[AUTH] Authentication failed: ${error}`);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Agent events
|
|
160
|
+
sdk.on("agent:selected", (data) => {
|
|
161
|
+
console.log(`\n[AGENT] Coordinator selected: ${data.agentName}`);
|
|
162
|
+
console.log(`[AGENT] Reasoning: ${data.reasoning}`);
|
|
163
|
+
if (data.command) {
|
|
164
|
+
console.log(`[AGENT] Command: ${data.command}`);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
sdk.on("agent:response", (response) => {
|
|
169
|
+
console.log(`\n[AGENT] Response from ${response.agentName || response.agentId}:`);
|
|
170
|
+
console.log(`[AGENT] Content: ${response.humanized || response.content}`);
|
|
171
|
+
if (response.error) {
|
|
172
|
+
console.log(`[AGENT] Error: ${response.error}`);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
sdk.on("agent:list", (agents) => {
|
|
177
|
+
console.log(`\n[AGENT] Agent list updated: ${agents.length} agents`);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Room events
|
|
181
|
+
sdk.on("room:subscribed", (data) => {
|
|
182
|
+
console.log(`[ROOM] Subscribed to room: ${data.roomId}`);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
sdk.on("room:unsubscribed", (data) => {
|
|
186
|
+
console.log(`[ROOM] Unsubscribed from room: ${data.roomId}`);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Webhook events
|
|
190
|
+
sdk.on("webhook:sent", (_payload, url) => {
|
|
191
|
+
console.log(`[WEBHOOK] Webhook sent to ${url}`);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
sdk.on("webhook:error", (error, url) => {
|
|
195
|
+
console.log(`[WEBHOOK] Webhook error for ${url}: ${error.message}`);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Error events
|
|
199
|
+
sdk.on("error", (error) => {
|
|
200
|
+
console.error(`[ERROR] SDK Error: ${error.message}`);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
sdk.on("warning", (warning) => {
|
|
204
|
+
console.warn(`[WARNING] ${warning}`);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Run the example
|
|
209
|
+
if (require.main === module) {
|
|
210
|
+
main().catch(console.error);
|
|
211
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Teneo Production Dashboard - Environment Configuration
|
|
2
|
+
# Copy this file to .env and fill in your values
|
|
3
|
+
|
|
4
|
+
# ============================================================================
|
|
5
|
+
# REQUIRED: Teneo Network Connection
|
|
6
|
+
# ============================================================================
|
|
7
|
+
|
|
8
|
+
# WebSocket URL for Teneo AI Network
|
|
9
|
+
WS_URL=wss://developer.chatroom.teneo-protocol.ai/ws
|
|
10
|
+
|
|
11
|
+
# Ethereum Private Key (with 0x prefix)
|
|
12
|
+
# IMPORTANT: Never commit your actual private key to version control!
|
|
13
|
+
PRIVATE_KEY=0x
|
|
14
|
+
|
|
15
|
+
# Ethereum Wallet Address (with 0x prefix)
|
|
16
|
+
# If not provided, will be derived from the private key
|
|
17
|
+
WALLET_ADDRESS=0x
|
|
18
|
+
|
|
19
|
+
# ============================================================================
|
|
20
|
+
# OPTIONAL: Room Configuration
|
|
21
|
+
# ============================================================================
|
|
22
|
+
|
|
23
|
+
# Default room to join on connection
|
|
24
|
+
# Leave empty to not auto-join any room
|
|
25
|
+
DEFAULT_ROOM=general
|
|
26
|
+
|
|
27
|
+
# Comma-separated list of rooms to auto-join
|
|
28
|
+
# Example: general,support,tech-help
|
|
29
|
+
# AUTO_JOIN_ROOMS=general,support
|
|
30
|
+
|
|
31
|
+
# ============================================================================
|
|
32
|
+
# OPTIONAL: Server Configuration
|
|
33
|
+
# ============================================================================
|
|
34
|
+
|
|
35
|
+
# Port for the dashboard server (default: 3000)
|
|
36
|
+
PORT=3000
|
|
37
|
+
|
|
38
|
+
# Node environment (development | production)
|
|
39
|
+
NODE_ENV=development
|
|
40
|
+
|
|
41
|
+
# ============================================================================
|
|
42
|
+
# OPTIONAL: Security Features
|
|
43
|
+
# ============================================================================
|
|
44
|
+
|
|
45
|
+
# Enable message signature verification (true | false)
|
|
46
|
+
# Verifies Ethereum signatures on incoming messages from agents
|
|
47
|
+
# Recommended: true for production
|
|
48
|
+
ENABLE_SIGNATURE_VERIFICATION=false
|
|
49
|
+
|
|
50
|
+
# Comma-separated list of trusted agent Ethereum addresses
|
|
51
|
+
# Only messages signed by these addresses will be accepted (if verification enabled)
|
|
52
|
+
# Leave empty to allow all signed messages
|
|
53
|
+
# Example: 0xAgent1...,0xAgent2...,0xAgent3...
|
|
54
|
+
TRUSTED_ADDRESSES=
|
|
55
|
+
|
|
56
|
+
# Require signatures for specific message types (comma-separated)
|
|
57
|
+
# Options: task_response,agent_selected,message,error
|
|
58
|
+
# Default: task_response,agent_selected
|
|
59
|
+
# REQUIRE_SIGNATURES_FOR=task_response,agent_selected
|
|
60
|
+
|
|
61
|
+
# Strict signature mode (true | false)
|
|
62
|
+
# true: Reject ALL unsigned messages
|
|
63
|
+
# false: Warn about unsigned messages but allow them
|
|
64
|
+
# STRICT_SIGNATURE_MODE=false
|
|
65
|
+
|
|
66
|
+
# ============================================================================
|
|
67
|
+
# OPTIONAL: Webhook Configuration
|
|
68
|
+
# ============================================================================
|
|
69
|
+
|
|
70
|
+
# Webhook URL to receive SDK events
|
|
71
|
+
# Auto-configured to localhost for development
|
|
72
|
+
# For production, use your publicly accessible webhook endpoint
|
|
73
|
+
# Example: https://api.example.com/webhooks/teneo
|
|
74
|
+
WEBHOOK_URL=http://localhost:3000/webhook
|
|
75
|
+
|
|
76
|
+
# Webhook authentication header (optional)
|
|
77
|
+
# WEBHOOK_AUTH_TOKEN=your-secret-token
|
|
78
|
+
|
|
79
|
+
# Max webhook retries on failure (0-10)
|
|
80
|
+
WEBHOOK_RETRIES=3
|
|
81
|
+
|
|
82
|
+
# Webhook timeout in milliseconds (1000-60000)
|
|
83
|
+
WEBHOOK_TIMEOUT=10000
|
|
84
|
+
|
|
85
|
+
# ============================================================================
|
|
86
|
+
# OPTIONAL: SDK Performance Tuning
|
|
87
|
+
# ============================================================================
|
|
88
|
+
|
|
89
|
+
# Enable agent caching (true | false)
|
|
90
|
+
ENABLE_CACHE=true
|
|
91
|
+
|
|
92
|
+
# Cache timeout in milliseconds (default: 300000 = 5 minutes)
|
|
93
|
+
CACHE_TIMEOUT=300000
|
|
94
|
+
|
|
95
|
+
# Maximum cache size (default: 100)
|
|
96
|
+
MAX_CACHE_SIZE=100
|
|
97
|
+
|
|
98
|
+
# ============================================================================
|
|
99
|
+
# OPTIONAL: Connection Settings
|
|
100
|
+
# ============================================================================
|
|
101
|
+
|
|
102
|
+
# Enable automatic reconnection (true | false)
|
|
103
|
+
ENABLE_RECONNECTION=true
|
|
104
|
+
|
|
105
|
+
# Reconnection delay in milliseconds (100-60000)
|
|
106
|
+
RECONNECT_DELAY=5000
|
|
107
|
+
|
|
108
|
+
# Maximum reconnection attempts (0-100, 0 = infinite)
|
|
109
|
+
MAX_RECONNECT_ATTEMPTS=10
|
|
110
|
+
|
|
111
|
+
# Connection timeout in milliseconds (1000-120000)
|
|
112
|
+
CONNECTION_TIMEOUT=30000
|
|
113
|
+
|
|
114
|
+
# ============================================================================
|
|
115
|
+
# OPTIONAL: Logging
|
|
116
|
+
# ============================================================================
|
|
117
|
+
|
|
118
|
+
# Log level (debug | info | warn | error | silent)
|
|
119
|
+
# debug: Very verbose, shows all SDK operations
|
|
120
|
+
# info: Normal operations and important events
|
|
121
|
+
# warn: Warnings and potential issues
|
|
122
|
+
# error: Errors only
|
|
123
|
+
# silent: No logging
|
|
124
|
+
LOG_LEVEL=info
|
|
125
|
+
|
|
126
|
+
# ============================================================================
|
|
127
|
+
# NOTES
|
|
128
|
+
# ============================================================================
|
|
129
|
+
|
|
130
|
+
# 1. Environment Precedence:
|
|
131
|
+
# - Environment variables override .env file values
|
|
132
|
+
# - .env file overrides default SDK values
|
|
133
|
+
#
|
|
134
|
+
# 2. Security Best Practices:
|
|
135
|
+
# - Never commit .env file to git (already in .gitignore)
|
|
136
|
+
# - Use different private keys for dev/prod
|
|
137
|
+
# - Enable signature verification in production
|
|
138
|
+
# - Use HTTPS webhooks in production
|
|
139
|
+
#
|
|
140
|
+
# 3. Development Tips:
|
|
141
|
+
# - Set LOG_LEVEL=debug for troubleshooting
|
|
142
|
+
# - Disable signature verification for local testing
|
|
143
|
+
# - Use localhost webhooks for development
|
|
144
|
+
#
|
|
145
|
+
# 4. Production Checklist:
|
|
146
|
+
# ✓ Use production WebSocket URL
|
|
147
|
+
# ✓ Use secure private key (from secrets manager)
|
|
148
|
+
# ✓ Enable signature verification
|
|
149
|
+
# ✓ Set trusted agent addresses
|
|
150
|
+
# ✓ Use HTTPS webhook URLs
|
|
151
|
+
# ✓ Set LOG_LEVEL=info or warn
|
|
152
|
+
# ✓ Enable all security features
|
|
153
|
+
# ✓ Use environment variables (not .env file)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@teneo/production-dashboard-example",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Production-ready dashboard example for Teneo Protocol SDK using Hono and Bun",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "bun --watch server.ts",
|
|
9
|
+
"start": "bun run server.ts",
|
|
10
|
+
"build": "bun build server.ts --outdir dist --target bun",
|
|
11
|
+
"serve": "bun run dist/server.js"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"hono": "^4.0.0",
|
|
15
|
+
"@hono/node-server": "^1.8.0",
|
|
16
|
+
"dotenv": "^16.4.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/bun": "latest"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"bun": ">=1.0.0",
|
|
23
|
+
"node": ">=18.0.0"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"teneo",
|
|
27
|
+
"sdk",
|
|
28
|
+
"dashboard",
|
|
29
|
+
"hono",
|
|
30
|
+
"bun",
|
|
31
|
+
"websocket",
|
|
32
|
+
"ai",
|
|
33
|
+
"agents",
|
|
34
|
+
"example",
|
|
35
|
+
"production"
|
|
36
|
+
],
|
|
37
|
+
"author": "Teneo",
|
|
38
|
+
"license": "MIT"
|
|
39
|
+
}
|