@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,677 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response formatter for Teneo Protocol SDK using Zod schemas
|
|
3
|
+
* Provides humanized and raw formatting for agent responses with validation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import {
|
|
8
|
+
BaseMessage,
|
|
9
|
+
TaskResponseMessage,
|
|
10
|
+
AgentSelectedMessage,
|
|
11
|
+
ErrorMessage,
|
|
12
|
+
Agent,
|
|
13
|
+
ContentTypeSchema,
|
|
14
|
+
TaskResponseMessageSchema,
|
|
15
|
+
AgentSelectedMessageSchema,
|
|
16
|
+
ErrorMessageSchema,
|
|
17
|
+
AgentSchema
|
|
18
|
+
} from "../types";
|
|
19
|
+
|
|
20
|
+
// Format option schema
|
|
21
|
+
export const FormatOptionSchema = z.enum(["raw", "humanized", "both"]);
|
|
22
|
+
export type FormatOption = z.infer<typeof FormatOptionSchema>;
|
|
23
|
+
|
|
24
|
+
// Response format options schema
|
|
25
|
+
export const ResponseFormatOptionsSchema = z.object({
|
|
26
|
+
format: FormatOptionSchema.optional(),
|
|
27
|
+
includeMetadata: z.boolean().optional(),
|
|
28
|
+
includeTimestamps: z.boolean().optional(),
|
|
29
|
+
prettyPrint: z.boolean().optional()
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export type ResponseFormatOptions = z.infer<typeof ResponseFormatOptionsSchema>;
|
|
33
|
+
|
|
34
|
+
// Response metadata schema
|
|
35
|
+
export const ResponseMetadataSchema = z.object({
|
|
36
|
+
timestamp: z.date(),
|
|
37
|
+
messageType: z.string(),
|
|
38
|
+
agentId: z.string().optional(),
|
|
39
|
+
agentName: z.string().optional(),
|
|
40
|
+
taskId: z.string().optional(),
|
|
41
|
+
success: z.boolean().optional(),
|
|
42
|
+
contentType: ContentTypeSchema.optional(),
|
|
43
|
+
reasoning: z.string().optional()
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Formatted response schema
|
|
47
|
+
export const FormattedResponseSchema = z.object({
|
|
48
|
+
raw: z.any().optional(),
|
|
49
|
+
humanized: z.string().optional(),
|
|
50
|
+
metadata: ResponseMetadataSchema.optional()
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Type inference
|
|
54
|
+
export type ResponseMetadata = z.infer<typeof ResponseMetadataSchema>;
|
|
55
|
+
export type FormattedResponse = z.infer<typeof FormattedResponseSchema>;
|
|
56
|
+
|
|
57
|
+
export class ResponseFormatter {
|
|
58
|
+
private formatOption: FormatOption;
|
|
59
|
+
private includeMetadata: boolean;
|
|
60
|
+
private includeTimestamps: boolean;
|
|
61
|
+
private prettyPrint: boolean;
|
|
62
|
+
|
|
63
|
+
constructor(options: ResponseFormatOptions = {}) {
|
|
64
|
+
const validatedOptions = ResponseFormatOptionsSchema.parse(options);
|
|
65
|
+
|
|
66
|
+
this.formatOption = validatedOptions.format ?? "humanized";
|
|
67
|
+
this.includeMetadata = validatedOptions.includeMetadata ?? false;
|
|
68
|
+
this.includeTimestamps = validatedOptions.includeTimestamps ?? true;
|
|
69
|
+
this.prettyPrint = validatedOptions.prettyPrint ?? true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Formats a message based on current configuration settings.
|
|
74
|
+
* Automatically determines the message type and applies appropriate formatting.
|
|
75
|
+
* Supports raw JSON, humanized text, or both formats simultaneously.
|
|
76
|
+
*
|
|
77
|
+
* @param message - The message to format
|
|
78
|
+
* @returns Formatted response with raw/humanized content and optional metadata
|
|
79
|
+
* @throws {ZodError} If message validation fails
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const formatter = new ResponseFormatter({ format: 'both', includeMetadata: true });
|
|
84
|
+
* const formatted = formatter.format(message);
|
|
85
|
+
* console.log(formatted.humanized); // Human-readable text
|
|
86
|
+
* console.log(formatted.raw); // Original JSON
|
|
87
|
+
* console.log(formatted.metadata); // Timestamp, agent info, etc.
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
public format(message: BaseMessage): FormattedResponse {
|
|
91
|
+
const response: FormattedResponse = {};
|
|
92
|
+
|
|
93
|
+
// Add metadata if requested
|
|
94
|
+
if (this.includeMetadata) {
|
|
95
|
+
response.metadata = this.extractMetadata(message);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Format based on option
|
|
99
|
+
if (this.formatOption === "raw" || this.formatOption === "both") {
|
|
100
|
+
response.raw = this.formatRaw(message);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (this.formatOption === "humanized" || this.formatOption === "both") {
|
|
104
|
+
response.humanized = this.formatHumanized(message);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Validate the response
|
|
108
|
+
return FormattedResponseSchema.parse(response);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Formats a task response message from an agent.
|
|
113
|
+
* Handles different content types (JSON, Markdown, plain text, arrays)
|
|
114
|
+
* and formats them appropriately for human consumption.
|
|
115
|
+
* Includes agent name, success status, reasoning, and formatted content.
|
|
116
|
+
*
|
|
117
|
+
* @param message - The task response message to format
|
|
118
|
+
* @returns Formatted response with task-specific formatting
|
|
119
|
+
* @throws {ZodError} If message validation fails
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const formatted = formatter.formatTaskResponse(taskMessage);
|
|
124
|
+
* // Example output:
|
|
125
|
+
* // [RESPONSE] From Weather Agent:
|
|
126
|
+
* // Temperature: 72°F
|
|
127
|
+
* // Conditions: Sunny
|
|
128
|
+
* // [REASONING] Used latest weather API data
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
public formatTaskResponse(message: TaskResponseMessage): FormattedResponse {
|
|
132
|
+
// Validate input
|
|
133
|
+
const validatedMessage = TaskResponseMessageSchema.parse(message);
|
|
134
|
+
const response: FormattedResponse = {};
|
|
135
|
+
|
|
136
|
+
if (this.includeMetadata) {
|
|
137
|
+
response.metadata = ResponseMetadataSchema.parse({
|
|
138
|
+
timestamp: new Date(validatedMessage.timestamp ?? Date.now()),
|
|
139
|
+
messageType: "task_response",
|
|
140
|
+
agentId: validatedMessage.from,
|
|
141
|
+
agentName: validatedMessage.data?.agent_name,
|
|
142
|
+
taskId: validatedMessage.data?.task_id,
|
|
143
|
+
success: validatedMessage.data?.success !== false,
|
|
144
|
+
contentType: validatedMessage.content_type,
|
|
145
|
+
reasoning: validatedMessage.reasoning
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (this.formatOption === "raw" || this.formatOption === "both") {
|
|
150
|
+
response.raw = validatedMessage;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (this.formatOption === "humanized" || this.formatOption === "both") {
|
|
154
|
+
response.humanized = this.formatTaskResponseHumanized(validatedMessage);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return FormattedResponseSchema.parse(response);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Formats an agent selection message from the coordinator.
|
|
162
|
+
* Shows which agent was selected, the command being executed,
|
|
163
|
+
* the reasoning behind the selection, and agent capabilities.
|
|
164
|
+
*
|
|
165
|
+
* @param message - The agent selection message to format
|
|
166
|
+
* @returns Formatted response with agent selection details
|
|
167
|
+
* @throws {ZodError} If message validation fails
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const formatted = formatter.formatAgentSelected(selectionMessage);
|
|
172
|
+
* // Example output:
|
|
173
|
+
* // [AGENT] Coordinator selected Weather Agent
|
|
174
|
+
* // [COMMAND] Get forecast for New York
|
|
175
|
+
* // [REASONING] Agent has weather-forecast capability
|
|
176
|
+
* // [CAPABILITIES]
|
|
177
|
+
* // - weather-forecast: Provides weather forecasts
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
public formatAgentSelected(message: AgentSelectedMessage): FormattedResponse {
|
|
181
|
+
// Validate input
|
|
182
|
+
const validatedMessage = AgentSelectedMessageSchema.parse(message);
|
|
183
|
+
const response: FormattedResponse = {};
|
|
184
|
+
|
|
185
|
+
if (this.includeMetadata) {
|
|
186
|
+
response.metadata = ResponseMetadataSchema.parse({
|
|
187
|
+
timestamp: new Date(validatedMessage.timestamp ?? Date.now()),
|
|
188
|
+
messageType: "agent_selected",
|
|
189
|
+
agentId: validatedMessage.data?.agent_id,
|
|
190
|
+
agentName: validatedMessage.data?.agent_name,
|
|
191
|
+
reasoning: validatedMessage.reasoning
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (this.formatOption === "raw" || this.formatOption === "both") {
|
|
196
|
+
response.raw = validatedMessage;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (this.formatOption === "humanized" || this.formatOption === "both") {
|
|
200
|
+
response.humanized = this.formatAgentSelectedHumanized(validatedMessage);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return FormattedResponseSchema.parse(response);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Formats an error message with error code and details.
|
|
208
|
+
* Displays error message, optional error code, and detailed information
|
|
209
|
+
* in a human-readable format.
|
|
210
|
+
*
|
|
211
|
+
* @param message - The error message to format
|
|
212
|
+
* @returns Formatted response with error information
|
|
213
|
+
* @throws {ZodError} If message validation fails
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```typescript
|
|
217
|
+
* const formatted = formatter.formatError(errorMessage);
|
|
218
|
+
* // Example output:
|
|
219
|
+
* // [ERROR] Agent not found (Code: AGENT_NOT_FOUND)
|
|
220
|
+
* // Details: {
|
|
221
|
+
* // "requestedAgent": "unknown-agent",
|
|
222
|
+
* // "availableAgents": 5
|
|
223
|
+
* // }
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
public formatError(message: ErrorMessage): FormattedResponse {
|
|
227
|
+
// Validate input
|
|
228
|
+
const validatedMessage = ErrorMessageSchema.parse(message);
|
|
229
|
+
const response: FormattedResponse = {};
|
|
230
|
+
|
|
231
|
+
if (this.includeMetadata) {
|
|
232
|
+
response.metadata = ResponseMetadataSchema.parse({
|
|
233
|
+
timestamp: new Date(validatedMessage.timestamp ?? Date.now()),
|
|
234
|
+
messageType: "error",
|
|
235
|
+
success: false
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (this.formatOption === "raw" || this.formatOption === "both") {
|
|
240
|
+
response.raw = validatedMessage;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (this.formatOption === "humanized" || this.formatOption === "both") {
|
|
244
|
+
response.humanized = this.formatErrorHumanized(validatedMessage);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return FormattedResponseSchema.parse(response);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Formats a list of agents with their details, capabilities, and commands.
|
|
252
|
+
* Displays each agent's name, status, description, room, capabilities, and available commands.
|
|
253
|
+
*
|
|
254
|
+
* @param agents - Array of agents to format
|
|
255
|
+
* @returns Formatted response with agent list
|
|
256
|
+
* @throws {ZodError} If agent validation fails
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* const formatted = formatter.formatAgentList(agents);
|
|
261
|
+
* // Example output:
|
|
262
|
+
* // [AGENTS] Available Agents (3):
|
|
263
|
+
* //
|
|
264
|
+
* // [AGENT] Weather Agent [ONLINE]
|
|
265
|
+
* // Provides weather forecasts and conditions
|
|
266
|
+
* // Room: general
|
|
267
|
+
* // Capabilities:
|
|
268
|
+
* // - weather-forecast
|
|
269
|
+
* // Commands:
|
|
270
|
+
* // - /weather <location>
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
public formatAgentList(agents: Agent[]): FormattedResponse {
|
|
274
|
+
// Validate input
|
|
275
|
+
const validatedAgents = z.array(AgentSchema).parse(agents);
|
|
276
|
+
const response: FormattedResponse = {};
|
|
277
|
+
|
|
278
|
+
if (this.includeMetadata) {
|
|
279
|
+
response.metadata = ResponseMetadataSchema.parse({
|
|
280
|
+
timestamp: new Date(),
|
|
281
|
+
messageType: "agents_list"
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (this.formatOption === "raw" || this.formatOption === "both") {
|
|
286
|
+
response.raw = validatedAgents;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (this.formatOption === "humanized" || this.formatOption === "both") {
|
|
290
|
+
response.humanized = this.formatAgentListHumanized(validatedAgents);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return FormattedResponseSchema.parse(response);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Format raw message (no transformation)
|
|
298
|
+
*/
|
|
299
|
+
private formatRaw(message: BaseMessage): any {
|
|
300
|
+
return message;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Format message as humanized text
|
|
305
|
+
*/
|
|
306
|
+
private formatHumanized(message: BaseMessage): string {
|
|
307
|
+
switch (message.type) {
|
|
308
|
+
case "task_response":
|
|
309
|
+
return this.formatTaskResponseHumanized(message as TaskResponseMessage);
|
|
310
|
+
|
|
311
|
+
case "agent_selected":
|
|
312
|
+
return this.formatAgentSelectedHumanized(message as AgentSelectedMessage);
|
|
313
|
+
|
|
314
|
+
case "error":
|
|
315
|
+
return this.formatErrorHumanized(message as ErrorMessage);
|
|
316
|
+
|
|
317
|
+
case "message":
|
|
318
|
+
return this.formatMessageHumanized(message);
|
|
319
|
+
|
|
320
|
+
default:
|
|
321
|
+
return message.content || JSON.stringify(message.data || {});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Format task response as humanized text
|
|
327
|
+
*/
|
|
328
|
+
private formatTaskResponseHumanized(message: TaskResponseMessage): string {
|
|
329
|
+
const agentName = message.data?.agent_name || message.from || "Agent";
|
|
330
|
+
const success = message.data?.success !== false;
|
|
331
|
+
|
|
332
|
+
let result = `[RESPONSE] From ${agentName}:\n`;
|
|
333
|
+
|
|
334
|
+
if (!success && message.data?.error) {
|
|
335
|
+
result += `[ERROR] ${message.data.error}\n`;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Format content based on content type
|
|
339
|
+
if (message.content_type === "application/json" || message.content_type === "JSON") {
|
|
340
|
+
try {
|
|
341
|
+
const json =
|
|
342
|
+
typeof message.content === "string" ? JSON.parse(message.content) : message.content;
|
|
343
|
+
result += this.formatJSON(json);
|
|
344
|
+
} catch {
|
|
345
|
+
result += message.content;
|
|
346
|
+
}
|
|
347
|
+
} else if (message.content_type === "text/markdown" || message.content_type === "MD") {
|
|
348
|
+
result += message.content;
|
|
349
|
+
} else if (message.content_type === "ARRAY") {
|
|
350
|
+
try {
|
|
351
|
+
const array =
|
|
352
|
+
typeof message.content === "string" ? JSON.parse(message.content) : message.content;
|
|
353
|
+
result += this.formatArray(array);
|
|
354
|
+
} catch {
|
|
355
|
+
result += message.content;
|
|
356
|
+
}
|
|
357
|
+
} else {
|
|
358
|
+
result += message.content;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (message.reasoning) {
|
|
362
|
+
result += `\n[REASONING] ${message.reasoning}`;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Format agent selection as humanized text
|
|
370
|
+
*/
|
|
371
|
+
private formatAgentSelectedHumanized(message: AgentSelectedMessage): string {
|
|
372
|
+
let result = `[AGENT] Coordinator selected ${message.data?.agent_name}`;
|
|
373
|
+
|
|
374
|
+
if (message.data?.command) {
|
|
375
|
+
result += `\n[COMMAND] ${message.data.command}`;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (message.reasoning) {
|
|
379
|
+
result += `\n[REASONING] ${message.reasoning}`;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (message.data?.capabilities && message.data.capabilities.length > 0) {
|
|
383
|
+
result += "\n[CAPABILITIES]";
|
|
384
|
+
for (const cap of message.data.capabilities) {
|
|
385
|
+
result += `\n - ${cap.name}: ${cap.description}`;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Format error as humanized text
|
|
394
|
+
*/
|
|
395
|
+
private formatErrorHumanized(message: ErrorMessage): string {
|
|
396
|
+
let result = `[ERROR] ${message.content || message.data?.message || "Unknown error"}`;
|
|
397
|
+
|
|
398
|
+
if (message.data?.code) {
|
|
399
|
+
result += ` (Code: ${message.data.code})`;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (message.data?.details) {
|
|
403
|
+
result += `\nDetails: ${JSON.stringify(message.data.details, null, 2)}`;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Format regular message as humanized text
|
|
411
|
+
*/
|
|
412
|
+
private formatMessageHumanized(message: BaseMessage): string {
|
|
413
|
+
const from = message.from || "Unknown";
|
|
414
|
+
let result = `[MESSAGE] ${from}: ${message.content}`;
|
|
415
|
+
|
|
416
|
+
if (message.room) {
|
|
417
|
+
result = `[${message.room}] ${result}`;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return result;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Format agent list as humanized text
|
|
425
|
+
*/
|
|
426
|
+
private formatAgentListHumanized(agents: Agent[]): string {
|
|
427
|
+
if (agents.length === 0) {
|
|
428
|
+
return "[AGENTS] No agents available";
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
let result = `[AGENTS] Available Agents (${agents.length}):\n`;
|
|
432
|
+
|
|
433
|
+
for (const agent of agents) {
|
|
434
|
+
result += `\n[AGENT] ${agent.name}`;
|
|
435
|
+
|
|
436
|
+
if (agent.status) {
|
|
437
|
+
const statusText = agent.status === "online" ? "ONLINE" : "OFFLINE";
|
|
438
|
+
result += ` [${statusText}]`;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (agent.description) {
|
|
442
|
+
result += `\n ${agent.description}`;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (agent.room) {
|
|
446
|
+
result += `\n Room: ${agent.room}`;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (agent.capabilities && agent.capabilities.length > 0) {
|
|
450
|
+
result += "\n Capabilities:";
|
|
451
|
+
for (const cap of agent.capabilities) {
|
|
452
|
+
result += `\n - ${cap.name}`;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (agent.commands && agent.commands.length > 0) {
|
|
457
|
+
result += "\n Commands:";
|
|
458
|
+
for (const cmd of agent.commands) {
|
|
459
|
+
result += `\n - ${cmd.trigger}${cmd.argument ? ` ${cmd.argument}` : ""}`;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Format JSON object for display
|
|
469
|
+
*/
|
|
470
|
+
private formatJSON(obj: any, indent = 0): string {
|
|
471
|
+
if (obj === null || obj === undefined) {
|
|
472
|
+
return "null";
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (typeof obj !== "object") {
|
|
476
|
+
return String(obj);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (Array.isArray(obj)) {
|
|
480
|
+
return this.formatArray(obj, indent);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const spaces = " ".repeat(indent);
|
|
484
|
+
let result = "";
|
|
485
|
+
|
|
486
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
487
|
+
if (typeof value === "object" && value !== null) {
|
|
488
|
+
result += `${spaces}${key}:\n${this.formatJSON(value, indent + 1)}`;
|
|
489
|
+
} else {
|
|
490
|
+
result += `${spaces}${key}: ${value}\n`;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return result;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Format array for display
|
|
499
|
+
*/
|
|
500
|
+
private formatArray(arr: any[], indent = 0): string {
|
|
501
|
+
if (arr.length === 0) {
|
|
502
|
+
return "[]";
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const spaces = " ".repeat(indent);
|
|
506
|
+
let result = "";
|
|
507
|
+
|
|
508
|
+
for (let i = 0; i < arr.length; i++) {
|
|
509
|
+
const item = arr[i];
|
|
510
|
+
if (typeof item === "object" && item !== null) {
|
|
511
|
+
result += `${spaces}[${i}]:\n${this.formatJSON(item, indent + 1)}`;
|
|
512
|
+
} else {
|
|
513
|
+
result += `${spaces}[${i}]: ${item}\n`;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return result;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Extract metadata from message with validation
|
|
522
|
+
*/
|
|
523
|
+
private extractMetadata(message: BaseMessage): ResponseMetadata {
|
|
524
|
+
return ResponseMetadataSchema.parse({
|
|
525
|
+
timestamp: new Date(message.timestamp ?? Date.now()),
|
|
526
|
+
messageType: message.type,
|
|
527
|
+
agentId: message.from,
|
|
528
|
+
agentName: message.data?.agent_name,
|
|
529
|
+
taskId: message.task_id ?? message.data?.task_id,
|
|
530
|
+
success: message.data?.success !== false,
|
|
531
|
+
contentType: message.content_type,
|
|
532
|
+
reasoning: message.reasoning
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Updates the format option for future formatting operations.
|
|
538
|
+
* Validates the option with Zod schema before applying.
|
|
539
|
+
*
|
|
540
|
+
* @param option - Format option: 'raw', 'humanized', or 'both'
|
|
541
|
+
* @throws {ZodError} If option is invalid
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```typescript
|
|
545
|
+
* formatter.setFormatOption('both');
|
|
546
|
+
* // Now all formatted responses include both raw and humanized formats
|
|
547
|
+
* ```
|
|
548
|
+
*/
|
|
549
|
+
public setFormatOption(option: FormatOption): void {
|
|
550
|
+
this.formatOption = FormatOptionSchema.parse(option);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Updates whether metadata should be included in formatted responses.
|
|
555
|
+
* Metadata includes timestamp, message type, agent info, task ID, success status, etc.
|
|
556
|
+
*
|
|
557
|
+
* @param include - Whether to include metadata in responses
|
|
558
|
+
* @throws {ZodError} If value is not a boolean
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
* ```typescript
|
|
562
|
+
* formatter.setIncludeMetadata(true);
|
|
563
|
+
* const formatted = formatter.format(message);
|
|
564
|
+
* console.log(formatted.metadata); // { timestamp, messageType, agentId, ... }
|
|
565
|
+
* ```
|
|
566
|
+
*/
|
|
567
|
+
public setIncludeMetadata(include: boolean): void {
|
|
568
|
+
this.includeMetadata = z.boolean().parse(include);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Updates multiple format options at once with validation.
|
|
573
|
+
* Allows configuring format type, metadata inclusion, timestamps, and pretty-printing.
|
|
574
|
+
*
|
|
575
|
+
* @param options - Response format configuration options
|
|
576
|
+
* @param options.format - Format type: 'raw', 'humanized', or 'both'
|
|
577
|
+
* @param options.includeMetadata - Whether to include metadata
|
|
578
|
+
* @param options.includeTimestamps - Whether to include timestamps
|
|
579
|
+
* @param options.prettyPrint - Whether to pretty-print JSON
|
|
580
|
+
* @throws {ZodError} If options fail validation
|
|
581
|
+
*
|
|
582
|
+
* @example
|
|
583
|
+
* ```typescript
|
|
584
|
+
* formatter.setFormatOptions({
|
|
585
|
+
* format: 'both',
|
|
586
|
+
* includeMetadata: true,
|
|
587
|
+
* prettyPrint: true
|
|
588
|
+
* });
|
|
589
|
+
* ```
|
|
590
|
+
*/
|
|
591
|
+
public setFormatOptions(options: ResponseFormatOptions): void {
|
|
592
|
+
const validatedOptions = ResponseFormatOptionsSchema.parse(options);
|
|
593
|
+
|
|
594
|
+
if (validatedOptions.format !== undefined) {
|
|
595
|
+
this.formatOption = validatedOptions.format;
|
|
596
|
+
}
|
|
597
|
+
if (validatedOptions.includeMetadata !== undefined) {
|
|
598
|
+
this.includeMetadata = validatedOptions.includeMetadata;
|
|
599
|
+
}
|
|
600
|
+
if (validatedOptions.includeTimestamps !== undefined) {
|
|
601
|
+
this.includeTimestamps = validatedOptions.includeTimestamps;
|
|
602
|
+
}
|
|
603
|
+
if (validatedOptions.prettyPrint !== undefined) {
|
|
604
|
+
this.prettyPrint = validatedOptions.prettyPrint;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Gets the current format configuration settings.
|
|
610
|
+
* Returns all current options including format type, metadata, timestamps, and pretty-print.
|
|
611
|
+
*
|
|
612
|
+
* @returns Current format options
|
|
613
|
+
*
|
|
614
|
+
* @example
|
|
615
|
+
* ```typescript
|
|
616
|
+
* const options = formatter.getFormatOptions();
|
|
617
|
+
* console.log(options.format); // 'both'
|
|
618
|
+
* console.log(options.includeMetadata); // true
|
|
619
|
+
* ```
|
|
620
|
+
*/
|
|
621
|
+
public getFormatOptions(): ResponseFormatOptions {
|
|
622
|
+
return {
|
|
623
|
+
format: this.formatOption,
|
|
624
|
+
includeMetadata: this.includeMetadata,
|
|
625
|
+
includeTimestamps: this.includeTimestamps,
|
|
626
|
+
prettyPrint: this.prettyPrint
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Static utility method that validates and formats any message in one step.
|
|
632
|
+
* Automatically detects message type and applies appropriate formatting.
|
|
633
|
+
* Useful for formatting messages without creating a formatter instance.
|
|
634
|
+
*
|
|
635
|
+
* @param message - Unknown message object to validate and format
|
|
636
|
+
* @param options - Optional format configuration
|
|
637
|
+
* @returns Formatted response with validated and formatted content
|
|
638
|
+
*
|
|
639
|
+
* @example
|
|
640
|
+
* ```typescript
|
|
641
|
+
* // Format unknown message from API
|
|
642
|
+
* const formatted = ResponseFormatter.validateAndFormat(unknownMessage, {
|
|
643
|
+
* format: 'humanized',
|
|
644
|
+
* includeMetadata: true
|
|
645
|
+
* });
|
|
646
|
+
*
|
|
647
|
+
* if (formatted.humanized) {
|
|
648
|
+
* console.log(formatted.humanized);
|
|
649
|
+
* }
|
|
650
|
+
* ```
|
|
651
|
+
*/
|
|
652
|
+
public static validateAndFormat(
|
|
653
|
+
message: unknown,
|
|
654
|
+
options: ResponseFormatOptions = {}
|
|
655
|
+
): FormattedResponse {
|
|
656
|
+
const formatter = new ResponseFormatter(options);
|
|
657
|
+
|
|
658
|
+
// Try to parse as different message types
|
|
659
|
+
const taskResponseResult = TaskResponseMessageSchema.safeParse(message);
|
|
660
|
+
if (taskResponseResult.success) {
|
|
661
|
+
return formatter.formatTaskResponse(taskResponseResult.data);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
const agentSelectedResult = AgentSelectedMessageSchema.safeParse(message);
|
|
665
|
+
if (agentSelectedResult.success) {
|
|
666
|
+
return formatter.formatAgentSelected(agentSelectedResult.data);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const errorResult = ErrorMessageSchema.safeParse(message);
|
|
670
|
+
if (errorResult.success) {
|
|
671
|
+
return formatter.formatError(errorResult.data);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Default to base message format
|
|
675
|
+
return formatter.format(message as BaseMessage);
|
|
676
|
+
}
|
|
677
|
+
}
|