@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,570 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core message schemas for Teneo Protocol SDK using Zod
|
|
3
|
+
* Provides runtime validation and TypeScript type inference
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Coerces string booleans to actual booleans with strict validation.
|
|
10
|
+
* The server sometimes sends "true"/"false" as strings instead of actual booleans.
|
|
11
|
+
*
|
|
12
|
+
* Accepts:
|
|
13
|
+
* - Booleans: true, false
|
|
14
|
+
* - Truthy strings (case-insensitive): "true", "1", "yes"
|
|
15
|
+
* - Falsy strings (case-insensitive): "false", "0", "no"
|
|
16
|
+
*
|
|
17
|
+
* Rejects: Any other string value (throws validation error)
|
|
18
|
+
*
|
|
19
|
+
* @throws {ZodError} If string value is not a recognized boolean representation
|
|
20
|
+
*/
|
|
21
|
+
const stringToBoolean = z
|
|
22
|
+
.union([
|
|
23
|
+
z.boolean(),
|
|
24
|
+
z.string().transform((val, ctx) => {
|
|
25
|
+
const normalized = val.toLowerCase().trim();
|
|
26
|
+
|
|
27
|
+
// Accept truthy values
|
|
28
|
+
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Accept falsy values
|
|
33
|
+
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Reject invalid values
|
|
38
|
+
ctx.addIssue({
|
|
39
|
+
code: z.ZodIssueCode.custom,
|
|
40
|
+
message: `Invalid boolean value: "${val}". Expected: true/false, yes/no, 1/0 (case-insensitive)`
|
|
41
|
+
});
|
|
42
|
+
return z.NEVER;
|
|
43
|
+
})
|
|
44
|
+
])
|
|
45
|
+
.pipe(z.boolean());
|
|
46
|
+
|
|
47
|
+
// Enum schemas
|
|
48
|
+
export const MessageTypeSchema = z.enum([
|
|
49
|
+
"request_challenge",
|
|
50
|
+
"challenge",
|
|
51
|
+
"check_cached_auth",
|
|
52
|
+
"auth",
|
|
53
|
+
"auth_required",
|
|
54
|
+
"auth_success",
|
|
55
|
+
"auth_error",
|
|
56
|
+
"register",
|
|
57
|
+
"registration_success",
|
|
58
|
+
"message",
|
|
59
|
+
"task",
|
|
60
|
+
"task_response",
|
|
61
|
+
"agent_selected",
|
|
62
|
+
"agents",
|
|
63
|
+
"error",
|
|
64
|
+
"ping",
|
|
65
|
+
"pong",
|
|
66
|
+
"capabilities",
|
|
67
|
+
"subscribe",
|
|
68
|
+
"unsubscribe",
|
|
69
|
+
"list_rooms"
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
export const ContentTypeSchema = z.enum([
|
|
73
|
+
"text/plain",
|
|
74
|
+
"text/markdown",
|
|
75
|
+
"text/html",
|
|
76
|
+
"application/json",
|
|
77
|
+
"image/*",
|
|
78
|
+
"STRING",
|
|
79
|
+
"JSON",
|
|
80
|
+
"MD",
|
|
81
|
+
"ARRAY"
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
export const ClientTypeSchema = z.enum(["user", "agent", "coordinator"]);
|
|
85
|
+
|
|
86
|
+
export const AgentTypeSchema = z.enum(["command", "nlp", "mcp"]);
|
|
87
|
+
|
|
88
|
+
export const AgentStatusSchema = z.enum(["online", "offline"]);
|
|
89
|
+
|
|
90
|
+
// Supporting schemas
|
|
91
|
+
export const CapabilitySchema = z.object({
|
|
92
|
+
name: z.string(),
|
|
93
|
+
description: z.string()
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export const CommandSchema = z.object({
|
|
97
|
+
trigger: z.string(),
|
|
98
|
+
argument: z.string().optional(),
|
|
99
|
+
description: z.string()
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
export const RoomSchema = z.object({
|
|
103
|
+
id: z.string(),
|
|
104
|
+
name: z.string(),
|
|
105
|
+
description: z.string().optional(),
|
|
106
|
+
is_public: stringToBoolean,
|
|
107
|
+
is_active: stringToBoolean,
|
|
108
|
+
created_by: z.string(),
|
|
109
|
+
created_at: z.string(),
|
|
110
|
+
updated_at: z.string()
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export const AgentSchema = z.object({
|
|
114
|
+
id: z.string(),
|
|
115
|
+
name: z.string(),
|
|
116
|
+
description: z.string().optional(),
|
|
117
|
+
room: z.string().optional(),
|
|
118
|
+
capabilities: z.array(CapabilitySchema).optional(),
|
|
119
|
+
commands: z.array(CommandSchema).optional(),
|
|
120
|
+
status: AgentStatusSchema,
|
|
121
|
+
image: z.string().optional(),
|
|
122
|
+
agentType: AgentTypeSchema.optional(),
|
|
123
|
+
nlpFallback: stringToBoolean.optional(),
|
|
124
|
+
webhookUrl: z.string().url().optional()
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Base message schema
|
|
128
|
+
export const BaseMessageSchema = z.object({
|
|
129
|
+
type: MessageTypeSchema,
|
|
130
|
+
content: z.any().optional(),
|
|
131
|
+
content_type: ContentTypeSchema.optional(),
|
|
132
|
+
from: z.string().optional(),
|
|
133
|
+
to: z.string().optional(),
|
|
134
|
+
room: z.string().optional(),
|
|
135
|
+
timestamp: z.string().optional(),
|
|
136
|
+
data: z.record(z.any()).optional(),
|
|
137
|
+
signature: z.string().optional(),
|
|
138
|
+
publicKey: z.string().optional(),
|
|
139
|
+
reasoning: z.string().optional(),
|
|
140
|
+
task_id: z.string().optional(),
|
|
141
|
+
id: z.string().optional() // Added for message tracking
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Authentication message schemas
|
|
145
|
+
export const RequestChallengeMessageSchema = BaseMessageSchema.extend({
|
|
146
|
+
type: z.literal("request_challenge"),
|
|
147
|
+
data: z.object({
|
|
148
|
+
userType: ClientTypeSchema,
|
|
149
|
+
address: z.string().optional()
|
|
150
|
+
})
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
export const ChallengeMessageSchema = BaseMessageSchema.extend({
|
|
154
|
+
type: z.literal("challenge"),
|
|
155
|
+
data: z.object({
|
|
156
|
+
challenge: z.string(),
|
|
157
|
+
timestamp: z.number()
|
|
158
|
+
})
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
export const CheckCachedAuthMessageSchema = BaseMessageSchema.extend({
|
|
162
|
+
type: z.literal("check_cached_auth"),
|
|
163
|
+
data: z.object({
|
|
164
|
+
address: z.string()
|
|
165
|
+
})
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
export const AuthRequiredMessageSchema = BaseMessageSchema.extend({
|
|
169
|
+
type: z.literal("auth_required"),
|
|
170
|
+
content: z.string().optional(),
|
|
171
|
+
from: z.literal("system").optional(),
|
|
172
|
+
data: z
|
|
173
|
+
.object({
|
|
174
|
+
cache_ttl_hours: z.number().optional(),
|
|
175
|
+
supported_auth_methods: z.array(z.string()).optional(),
|
|
176
|
+
supports_cache_check: z.boolean().optional()
|
|
177
|
+
})
|
|
178
|
+
.optional()
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
export const AuthMessageSchema = BaseMessageSchema.extend({
|
|
182
|
+
type: z.literal("auth"),
|
|
183
|
+
data: z
|
|
184
|
+
.object({
|
|
185
|
+
address: z.string().optional(),
|
|
186
|
+
signature: z.string().optional(),
|
|
187
|
+
message: z.string().optional(),
|
|
188
|
+
userType: ClientTypeSchema.optional(),
|
|
189
|
+
agentName: z.string().optional(),
|
|
190
|
+
id: z.string().optional(),
|
|
191
|
+
type: ClientTypeSchema.optional(),
|
|
192
|
+
nft_verified: stringToBoolean.optional(),
|
|
193
|
+
is_whitelisted: stringToBoolean.optional(),
|
|
194
|
+
is_admin_whitelisted: stringToBoolean.optional(),
|
|
195
|
+
rooms: z.array(RoomSchema).optional(),
|
|
196
|
+
private_room_id: z.string().optional(),
|
|
197
|
+
cached_auth: stringToBoolean.optional()
|
|
198
|
+
})
|
|
199
|
+
.optional()
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
export const AuthSuccessMessageSchema = BaseMessageSchema.extend({
|
|
203
|
+
type: z.literal("auth_success"),
|
|
204
|
+
data: z.object({
|
|
205
|
+
id: z.string(),
|
|
206
|
+
type: ClientTypeSchema,
|
|
207
|
+
address: z.string(),
|
|
208
|
+
nft_verified: stringToBoolean.optional(),
|
|
209
|
+
is_whitelisted: stringToBoolean.optional(),
|
|
210
|
+
is_admin_whitelisted: stringToBoolean.optional(),
|
|
211
|
+
rooms: z.array(RoomSchema).optional(),
|
|
212
|
+
private_room_id: z.string().optional(),
|
|
213
|
+
cached_auth: stringToBoolean.optional()
|
|
214
|
+
})
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
export const AuthErrorMessageSchema = BaseMessageSchema.extend({
|
|
218
|
+
type: z.literal("auth_error"),
|
|
219
|
+
data: z.object({
|
|
220
|
+
error: z.string(),
|
|
221
|
+
code: z.number().optional()
|
|
222
|
+
})
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Registration message schemas
|
|
226
|
+
export const RegisterMessageSchema = BaseMessageSchema.extend({
|
|
227
|
+
type: z.literal("register"),
|
|
228
|
+
data: z.object({
|
|
229
|
+
name: z.string().optional(),
|
|
230
|
+
userType: ClientTypeSchema,
|
|
231
|
+
room: z.string(),
|
|
232
|
+
capabilities: z.array(CapabilitySchema).optional(),
|
|
233
|
+
commands: z.array(CommandSchema).optional(),
|
|
234
|
+
nft_token_id: z.string().optional(),
|
|
235
|
+
wallet_address: z.string().optional(),
|
|
236
|
+
challenge: z.string().optional(),
|
|
237
|
+
challenge_response: z.string().optional()
|
|
238
|
+
})
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
export const RegistrationSuccessMessageSchema = BaseMessageSchema.extend({
|
|
242
|
+
type: z.literal("registration_success"),
|
|
243
|
+
data: z.object({
|
|
244
|
+
agent_id: z.string(),
|
|
245
|
+
name: z.string(),
|
|
246
|
+
room: z.string()
|
|
247
|
+
})
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Communication message schemas
|
|
251
|
+
export const UserMessageSchema = BaseMessageSchema.extend({
|
|
252
|
+
type: z.literal("message"),
|
|
253
|
+
content: z.string(),
|
|
254
|
+
room: z.string().optional()
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
export const TaskMessageSchema = BaseMessageSchema.extend({
|
|
258
|
+
type: z.literal("task"),
|
|
259
|
+
content: z.string(),
|
|
260
|
+
from: z.literal("coordinator"),
|
|
261
|
+
to: z.string(),
|
|
262
|
+
room: z.string(),
|
|
263
|
+
data: z.object({
|
|
264
|
+
task_id: z.string(),
|
|
265
|
+
user_prompt: z.string(),
|
|
266
|
+
requesting_user_id: z.string(),
|
|
267
|
+
room_id: z.string()
|
|
268
|
+
})
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
export const TaskResponseMessageSchema = BaseMessageSchema.extend({
|
|
272
|
+
type: z.literal("task_response"),
|
|
273
|
+
content: z.string(),
|
|
274
|
+
content_type: ContentTypeSchema,
|
|
275
|
+
from: z.string(),
|
|
276
|
+
data: z.object({
|
|
277
|
+
task_id: z.string(),
|
|
278
|
+
agent_name: z.string().optional(),
|
|
279
|
+
success: stringToBoolean.optional(),
|
|
280
|
+
error: z.string().optional()
|
|
281
|
+
})
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
export const AgentSelectedMessageSchema = BaseMessageSchema.extend({
|
|
285
|
+
type: z.literal("agent_selected"),
|
|
286
|
+
content: z.string(),
|
|
287
|
+
from: z.literal("coordinator"),
|
|
288
|
+
reasoning: z.string(),
|
|
289
|
+
data: z.object({
|
|
290
|
+
agent_id: z.string(),
|
|
291
|
+
agent_name: z.string(),
|
|
292
|
+
capabilities: z.array(CapabilitySchema).optional(),
|
|
293
|
+
user_request: z.string(),
|
|
294
|
+
command: z.string().optional(),
|
|
295
|
+
command_reasoning: z.string().optional()
|
|
296
|
+
})
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// System message schemas
|
|
300
|
+
export const AgentsListMessageSchema = BaseMessageSchema.extend({
|
|
301
|
+
type: z.literal("agents"),
|
|
302
|
+
from: z.literal("system"),
|
|
303
|
+
data: z.array(AgentSchema)
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
export const ErrorMessageSchema = BaseMessageSchema.extend({
|
|
307
|
+
type: z.literal("error"),
|
|
308
|
+
content: z.string(),
|
|
309
|
+
from: z.literal("system"),
|
|
310
|
+
data: z.object({
|
|
311
|
+
code: z.number(),
|
|
312
|
+
message: z.string(),
|
|
313
|
+
details: z.any().optional()
|
|
314
|
+
})
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
export const PingMessageSchema = BaseMessageSchema.extend({
|
|
318
|
+
type: z.literal("ping")
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
export const PongMessageSchema = BaseMessageSchema.extend({
|
|
322
|
+
type: z.literal("pong")
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// Room subscription schemas
|
|
326
|
+
export const SubscribeMessageSchema = BaseMessageSchema.extend({
|
|
327
|
+
type: z.literal("subscribe"),
|
|
328
|
+
data: z.object({
|
|
329
|
+
room_id: z.string()
|
|
330
|
+
})
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
export const UnsubscribeMessageSchema = BaseMessageSchema.extend({
|
|
334
|
+
type: z.literal("unsubscribe"),
|
|
335
|
+
data: z.object({
|
|
336
|
+
room_id: z.string()
|
|
337
|
+
})
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
export const ListRoomsMessageSchema = BaseMessageSchema.extend({
|
|
341
|
+
type: z.literal("list_rooms")
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
export const SubscribeResponseSchema = BaseMessageSchema.extend({
|
|
345
|
+
type: z.literal("subscribe"),
|
|
346
|
+
data: z.object({
|
|
347
|
+
room_id: z.string(),
|
|
348
|
+
success: z.boolean(),
|
|
349
|
+
message: z.string(),
|
|
350
|
+
subscriptions: z.array(z.string()).optional()
|
|
351
|
+
})
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
export const UnsubscribeResponseSchema = BaseMessageSchema.extend({
|
|
355
|
+
type: z.literal("unsubscribe"),
|
|
356
|
+
data: z.object({
|
|
357
|
+
room_id: z.string(),
|
|
358
|
+
success: z.boolean(),
|
|
359
|
+
message: z.string(),
|
|
360
|
+
subscriptions: z.array(z.string()).optional()
|
|
361
|
+
})
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
export const RoomInfoSchema = z.object({
|
|
365
|
+
id: z.string(),
|
|
366
|
+
name: z.string(),
|
|
367
|
+
description: z.string().optional().nullable(),
|
|
368
|
+
is_public: z.boolean(),
|
|
369
|
+
created_at: z.string(),
|
|
370
|
+
updated_at: z.string(),
|
|
371
|
+
is_owner: z.boolean()
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
export const ListRoomsResponseSchema = BaseMessageSchema.extend({
|
|
375
|
+
type: z.literal("list_rooms"),
|
|
376
|
+
data: z.object({
|
|
377
|
+
rooms: z.array(RoomInfoSchema)
|
|
378
|
+
})
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// Union of all INCOMING message schemas for validation
|
|
382
|
+
// Note: Outgoing message schemas (Subscribe, Unsubscribe, ListRooms) are excluded
|
|
383
|
+
// as they share the same type values with their response counterparts
|
|
384
|
+
export const AnyMessageSchema = z.discriminatedUnion("type", [
|
|
385
|
+
RequestChallengeMessageSchema,
|
|
386
|
+
ChallengeMessageSchema,
|
|
387
|
+
CheckCachedAuthMessageSchema,
|
|
388
|
+
AuthRequiredMessageSchema,
|
|
389
|
+
AuthMessageSchema,
|
|
390
|
+
AuthSuccessMessageSchema,
|
|
391
|
+
AuthErrorMessageSchema,
|
|
392
|
+
RegisterMessageSchema,
|
|
393
|
+
RegistrationSuccessMessageSchema,
|
|
394
|
+
UserMessageSchema,
|
|
395
|
+
TaskMessageSchema,
|
|
396
|
+
TaskResponseMessageSchema,
|
|
397
|
+
AgentSelectedMessageSchema,
|
|
398
|
+
AgentsListMessageSchema,
|
|
399
|
+
ErrorMessageSchema,
|
|
400
|
+
PingMessageSchema,
|
|
401
|
+
PongMessageSchema,
|
|
402
|
+
// Only response schemas for room operations (not outgoing request schemas)
|
|
403
|
+
SubscribeResponseSchema,
|
|
404
|
+
UnsubscribeResponseSchema,
|
|
405
|
+
ListRoomsResponseSchema
|
|
406
|
+
]);
|
|
407
|
+
|
|
408
|
+
// Type inference from schemas
|
|
409
|
+
export type MessageType = z.infer<typeof MessageTypeSchema>;
|
|
410
|
+
export type ContentType = z.infer<typeof ContentTypeSchema>;
|
|
411
|
+
export type ClientType = z.infer<typeof ClientTypeSchema>;
|
|
412
|
+
export type AgentType = z.infer<typeof AgentTypeSchema>;
|
|
413
|
+
export type AgentStatus = z.infer<typeof AgentStatusSchema>;
|
|
414
|
+
|
|
415
|
+
export type Capability = z.infer<typeof CapabilitySchema>;
|
|
416
|
+
export type Command = z.infer<typeof CommandSchema>;
|
|
417
|
+
export type Room = z.infer<typeof RoomSchema>;
|
|
418
|
+
export type Agent = z.infer<typeof AgentSchema>;
|
|
419
|
+
|
|
420
|
+
export type BaseMessage = z.infer<typeof BaseMessageSchema>;
|
|
421
|
+
export type RequestChallengeMessage = z.infer<typeof RequestChallengeMessageSchema>;
|
|
422
|
+
export type ChallengeMessage = z.infer<typeof ChallengeMessageSchema>;
|
|
423
|
+
export type CheckCachedAuthMessage = z.infer<typeof CheckCachedAuthMessageSchema>;
|
|
424
|
+
export type AuthRequiredMessage = z.infer<typeof AuthRequiredMessageSchema>;
|
|
425
|
+
export type AuthMessage = z.infer<typeof AuthMessageSchema>;
|
|
426
|
+
export type AuthSuccessMessage = z.infer<typeof AuthSuccessMessageSchema>;
|
|
427
|
+
export type AuthErrorMessage = z.infer<typeof AuthErrorMessageSchema>;
|
|
428
|
+
export type RegisterMessage = z.infer<typeof RegisterMessageSchema>;
|
|
429
|
+
export type RegistrationSuccessMessage = z.infer<typeof RegistrationSuccessMessageSchema>;
|
|
430
|
+
export type UserMessage = z.infer<typeof UserMessageSchema>;
|
|
431
|
+
export type TaskMessage = z.infer<typeof TaskMessageSchema>;
|
|
432
|
+
export type TaskResponseMessage = z.infer<typeof TaskResponseMessageSchema>;
|
|
433
|
+
export type AgentSelectedMessage = z.infer<typeof AgentSelectedMessageSchema>;
|
|
434
|
+
export type AgentsListMessage = z.infer<typeof AgentsListMessageSchema>;
|
|
435
|
+
export type ErrorMessage = z.infer<typeof ErrorMessageSchema>;
|
|
436
|
+
export type PingMessage = z.infer<typeof PingMessageSchema>;
|
|
437
|
+
export type PongMessage = z.infer<typeof PongMessageSchema>;
|
|
438
|
+
export type SubscribeMessage = z.infer<typeof SubscribeMessageSchema>;
|
|
439
|
+
export type UnsubscribeMessage = z.infer<typeof UnsubscribeMessageSchema>;
|
|
440
|
+
export type ListRoomsMessage = z.infer<typeof ListRoomsMessageSchema>;
|
|
441
|
+
export type SubscribeResponse = z.infer<typeof SubscribeResponseSchema>;
|
|
442
|
+
export type UnsubscribeResponse = z.infer<typeof UnsubscribeResponseSchema>;
|
|
443
|
+
export type RoomInfo = z.infer<typeof RoomInfoSchema>;
|
|
444
|
+
export type ListRoomsResponse = z.infer<typeof ListRoomsResponseSchema>;
|
|
445
|
+
|
|
446
|
+
export type AnyMessage = z.infer<typeof AnyMessageSchema>;
|
|
447
|
+
|
|
448
|
+
// Type guards using Zod parse
|
|
449
|
+
export function isAuthSuccess(msg: unknown): msg is AuthSuccessMessage {
|
|
450
|
+
return AuthSuccessMessageSchema.safeParse(msg).success;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export function isAuthError(msg: unknown): msg is AuthErrorMessage {
|
|
454
|
+
return AuthErrorMessageSchema.safeParse(msg).success;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function isAuth(msg: unknown): msg is AuthMessage {
|
|
458
|
+
return AuthMessageSchema.safeParse(msg).success;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export function isChallenge(msg: unknown): msg is ChallengeMessage {
|
|
462
|
+
return ChallengeMessageSchema.safeParse(msg).success;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export function isAgentSelected(msg: unknown): msg is AgentSelectedMessage {
|
|
466
|
+
return AgentSelectedMessageSchema.safeParse(msg).success;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export function isTaskResponse(msg: unknown): msg is TaskResponseMessage {
|
|
470
|
+
return TaskResponseMessageSchema.safeParse(msg).success;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export function isError(msg: unknown): msg is ErrorMessage {
|
|
474
|
+
return ErrorMessageSchema.safeParse(msg).success;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export function isAgentsList(msg: unknown): msg is AgentsListMessage {
|
|
478
|
+
return AgentsListMessageSchema.safeParse(msg).success;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Message factory functions with validation
|
|
482
|
+
export function createRequestChallenge(
|
|
483
|
+
userType: ClientType = "user",
|
|
484
|
+
address?: string
|
|
485
|
+
): RequestChallengeMessage {
|
|
486
|
+
return RequestChallengeMessageSchema.parse({
|
|
487
|
+
type: "request_challenge",
|
|
488
|
+
data: {
|
|
489
|
+
userType,
|
|
490
|
+
...(address && { address })
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export function createCheckCachedAuth(address: string): CheckCachedAuthMessage {
|
|
496
|
+
return CheckCachedAuthMessageSchema.parse({
|
|
497
|
+
type: "check_cached_auth",
|
|
498
|
+
data: { address }
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export function createAuth(
|
|
503
|
+
address: string,
|
|
504
|
+
signature: string,
|
|
505
|
+
message: string,
|
|
506
|
+
userType: ClientType = "user"
|
|
507
|
+
): AuthMessage {
|
|
508
|
+
return AuthMessageSchema.parse({
|
|
509
|
+
type: "auth",
|
|
510
|
+
data: {
|
|
511
|
+
address,
|
|
512
|
+
signature,
|
|
513
|
+
message,
|
|
514
|
+
userType
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export function createUserMessage(content: string, room: string, from?: string): UserMessage {
|
|
520
|
+
return UserMessageSchema.parse({
|
|
521
|
+
type: "message",
|
|
522
|
+
content,
|
|
523
|
+
room,
|
|
524
|
+
...(from && { from })
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export function createPing(): PingMessage {
|
|
529
|
+
return PingMessageSchema.parse({
|
|
530
|
+
type: "ping"
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export function createSubscribe(roomId: string): SubscribeMessage {
|
|
535
|
+
return SubscribeMessageSchema.parse({
|
|
536
|
+
type: "subscribe",
|
|
537
|
+
data: { room_id: roomId }
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
export function createUnsubscribe(roomId: string): UnsubscribeMessage {
|
|
542
|
+
return UnsubscribeMessageSchema.parse({
|
|
543
|
+
type: "unsubscribe",
|
|
544
|
+
data: { room_id: roomId }
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export function createListRooms(): ListRoomsMessage {
|
|
549
|
+
return ListRoomsMessageSchema.parse({
|
|
550
|
+
type: "list_rooms"
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// Validation helper
|
|
555
|
+
export function validateMessage(message: unknown): AnyMessage {
|
|
556
|
+
return AnyMessageSchema.parse(message);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Safe parse helper
|
|
560
|
+
export function safeParseMessage(message: unknown): {
|
|
561
|
+
success: boolean;
|
|
562
|
+
data?: AnyMessage;
|
|
563
|
+
error?: z.ZodError;
|
|
564
|
+
} {
|
|
565
|
+
const result = AnyMessageSchema.safeParse(message);
|
|
566
|
+
if (result.success) {
|
|
567
|
+
return { success: true, data: result.data };
|
|
568
|
+
}
|
|
569
|
+
return { success: false, error: result.error };
|
|
570
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation schemas for user inputs
|
|
3
|
+
* Provides strict validation with length limits, character restrictions, and format requirements
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Validates room IDs with strict constraints.
|
|
10
|
+
* - Must not be empty
|
|
11
|
+
* - Maximum 100 characters
|
|
12
|
+
* - Only alphanumeric characters, spaces, dashes, and underscores allowed
|
|
13
|
+
* - Automatically trims whitespace
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const roomId = RoomIdSchema.parse('general-chat'); // OK
|
|
18
|
+
* const roomId = RoomIdSchema.parse('room_123'); // OK
|
|
19
|
+
* const roomId = RoomIdSchema.parse('Crawler Room'); // OK
|
|
20
|
+
* const roomId = RoomIdSchema.parse('invalid room!'); // Error: invalid characters
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const RoomIdSchema = z
|
|
24
|
+
.string()
|
|
25
|
+
.min(1, "Room ID cannot be empty")
|
|
26
|
+
.max(100, "Room ID must be 100 characters or less")
|
|
27
|
+
.regex(/^[a-zA-Z0-9_\- ]+$/, "Room ID can only contain letters, numbers, spaces, dashes, and underscores")
|
|
28
|
+
.trim();
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Validates agent IDs with strict constraints.
|
|
32
|
+
* - Must not be empty
|
|
33
|
+
* - Maximum 100 characters
|
|
34
|
+
* - Only alphanumeric characters, dashes, and underscores allowed
|
|
35
|
+
* - Automatically trims whitespace
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const agentId = AgentIdSchema.parse('agent-123'); // OK
|
|
40
|
+
* const agentId = AgentIdSchema.parse('my_agent'); // OK
|
|
41
|
+
* const agentId = AgentIdSchema.parse('invalid agent!'); // Error: invalid characters
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export const AgentIdSchema = z
|
|
45
|
+
.string()
|
|
46
|
+
.min(1, "Agent ID cannot be empty")
|
|
47
|
+
.max(100, "Agent ID must be 100 characters or less")
|
|
48
|
+
.regex(/^[a-zA-Z0-9_-]+$/, "Agent ID can only contain letters, numbers, dashes, and underscores")
|
|
49
|
+
.trim();
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Validates message content with strict constraints.
|
|
53
|
+
* - Must not be empty
|
|
54
|
+
* - Maximum 10,000 characters to prevent abuse
|
|
55
|
+
* - No control characters (except newline, tab, carriage return)
|
|
56
|
+
* - Automatically trims whitespace
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const content = MessageContentSchema.parse('Hello, world!'); // OK
|
|
61
|
+
* const content = MessageContentSchema.parse('Multi\nline\nmessage'); // OK
|
|
62
|
+
* const content = MessageContentSchema.parse('\x00Bad content'); // Error: control characters
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export const MessageContentSchema = z
|
|
66
|
+
.string()
|
|
67
|
+
.trim()
|
|
68
|
+
.min(1, "Message content cannot be empty")
|
|
69
|
+
.max(10000, "Message content must be 10,000 characters or less")
|
|
70
|
+
.refine(
|
|
71
|
+
// eslint-disable-next-line no-control-regex -- Intentionally checking for control characters to prevent injection
|
|
72
|
+
(str) => !/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(str),
|
|
73
|
+
"Message content cannot contain control characters"
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Validates agent command content (string) with strict constraints.
|
|
78
|
+
* - Must not be empty
|
|
79
|
+
* - Maximum 5,000 characters
|
|
80
|
+
* - No control characters (except newline, tab, carriage return)
|
|
81
|
+
* - Automatically trims whitespace
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const command = AgentCommandContentSchema.parse('execute task'); // OK
|
|
86
|
+
* const command = AgentCommandContentSchema.parse('multi\nline\ncommand'); // OK
|
|
87
|
+
* const command = AgentCommandContentSchema.parse('\x00Bad'); // Error: control characters
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export const AgentCommandContentSchema = z
|
|
91
|
+
.string()
|
|
92
|
+
.trim()
|
|
93
|
+
.min(1, "Agent command cannot be empty")
|
|
94
|
+
.max(5000, "Agent command must be 5,000 characters or less")
|
|
95
|
+
.refine(
|
|
96
|
+
// eslint-disable-next-line no-control-regex -- Intentionally checking for control characters to prevent injection
|
|
97
|
+
(str) => !/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(str),
|
|
98
|
+
"Agent command cannot contain control characters"
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Validates search queries with strict constraints.
|
|
103
|
+
* - Must not be empty
|
|
104
|
+
* - Maximum 200 characters (reasonable for search)
|
|
105
|
+
* - No control characters
|
|
106
|
+
* - Automatically trims whitespace
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const query = SearchQuerySchema.parse('find agents'); // OK
|
|
111
|
+
* const query = SearchQuerySchema.parse('\x00Bad query'); // Error: control characters
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export const SearchQuerySchema = z
|
|
115
|
+
.string()
|
|
116
|
+
.trim()
|
|
117
|
+
.min(1, "Search query cannot be empty")
|
|
118
|
+
.max(200, "Search query must be 200 characters or less")
|
|
119
|
+
.refine(
|
|
120
|
+
// eslint-disable-next-line no-control-regex -- Intentionally checking for control characters to prevent injection
|
|
121
|
+
(str) => !/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(str),
|
|
122
|
+
"Search query cannot contain control characters"
|
|
123
|
+
);
|