beddel 0.2.1 → 0.2.3
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/CHANGELOG.md +20 -0
- package/README.md +132 -21
- package/dist/agents/chat/chat.handler.d.ts +12 -0
- package/dist/agents/chat/chat.handler.d.ts.map +1 -0
- package/dist/agents/chat/chat.handler.js +143 -0
- package/dist/agents/chat/chat.handler.js.map +1 -0
- package/dist/agents/chat/chat.schema.d.ts +38 -0
- package/dist/agents/chat/chat.schema.d.ts.map +1 -0
- package/dist/agents/chat/chat.schema.js +31 -0
- package/dist/agents/chat/chat.schema.js.map +1 -0
- package/dist/agents/chat/chat.types.d.ts +42 -0
- package/dist/agents/chat/chat.types.d.ts.map +1 -0
- package/dist/agents/chat/chat.types.js +6 -0
- package/dist/agents/chat/chat.types.js.map +1 -0
- package/dist/agents/chat/chat.yaml +150 -0
- package/dist/agents/chat/index.d.ts +16 -0
- package/dist/agents/chat/index.d.ts.map +1 -0
- package/dist/agents/chat/index.js +21 -0
- package/dist/agents/chat/index.js.map +1 -0
- package/dist/agents/chromadb/chromadb.handler.d.ts +12 -0
- package/dist/agents/chromadb/chromadb.handler.d.ts.map +1 -0
- package/dist/agents/chromadb/chromadb.handler.js +139 -0
- package/dist/agents/chromadb/chromadb.handler.js.map +1 -0
- package/dist/agents/chromadb/chromadb.schema.d.ts +36 -0
- package/dist/agents/chromadb/chromadb.schema.d.ts.map +1 -0
- package/dist/agents/chromadb/chromadb.schema.js +33 -0
- package/dist/agents/chromadb/chromadb.schema.js.map +1 -0
- package/dist/agents/chromadb/chromadb.types.d.ts +49 -0
- package/dist/agents/chromadb/chromadb.types.d.ts.map +1 -0
- package/dist/agents/chromadb/chromadb.types.js +6 -0
- package/dist/agents/chromadb/chromadb.types.js.map +1 -0
- package/dist/agents/chromadb/chromadb.yaml +128 -0
- package/dist/agents/chromadb/index.d.ts +15 -0
- package/dist/agents/chromadb/index.d.ts.map +1 -0
- package/dist/agents/chromadb/index.js +20 -0
- package/dist/agents/chromadb/index.js.map +1 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.handler.d.ts +8 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.handler.d.ts.map +1 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.handler.js +58 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.handler.js.map +1 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.schema.d.ts +22 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.schema.d.ts.map +1 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.schema.js +20 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.schema.js.map +1 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.types.d.ts +32 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.types.d.ts.map +1 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.types.js +6 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.types.js.map +1 -0
- package/dist/agents/gemini-vectorize/gemini-vectorize.yaml +84 -0
- package/dist/agents/gemini-vectorize/index.d.ts +15 -0
- package/dist/agents/gemini-vectorize/index.d.ts.map +1 -0
- package/dist/agents/gemini-vectorize/index.js +20 -0
- package/dist/agents/gemini-vectorize/index.js.map +1 -0
- package/dist/agents/gitmcp/gitmcp.handler.d.ts +12 -0
- package/dist/agents/gitmcp/gitmcp.handler.d.ts.map +1 -0
- package/dist/agents/gitmcp/gitmcp.handler.js +95 -0
- package/dist/agents/gitmcp/gitmcp.handler.js.map +1 -0
- package/dist/agents/gitmcp/gitmcp.schema.d.ts +17 -0
- package/dist/agents/gitmcp/gitmcp.schema.d.ts.map +1 -0
- package/dist/agents/gitmcp/gitmcp.schema.js +18 -0
- package/dist/agents/gitmcp/gitmcp.schema.js.map +1 -0
- package/dist/agents/gitmcp/gitmcp.types.d.ts +31 -0
- package/dist/agents/gitmcp/gitmcp.types.d.ts.map +1 -0
- package/dist/agents/gitmcp/gitmcp.types.js +6 -0
- package/dist/agents/gitmcp/gitmcp.types.js.map +1 -0
- package/dist/agents/gitmcp/gitmcp.yaml +71 -0
- package/dist/agents/gitmcp/index.d.ts +16 -0
- package/dist/agents/gitmcp/index.d.ts.map +1 -0
- package/dist/agents/gitmcp/index.js +21 -0
- package/dist/agents/gitmcp/index.js.map +1 -0
- package/dist/agents/image/image.handler.d.ts +8 -0
- package/dist/agents/image/image.handler.d.ts.map +1 -0
- package/dist/agents/image/image.handler.js +66 -0
- package/dist/agents/image/image.handler.js.map +1 -0
- package/dist/agents/image/image.schema.d.ts +29 -0
- package/dist/agents/image/image.schema.d.ts.map +1 -0
- package/dist/agents/image/image.schema.js +26 -0
- package/dist/agents/image/image.schema.js.map +1 -0
- package/dist/agents/image/image.types.d.ts +42 -0
- package/dist/agents/image/image.types.d.ts.map +1 -0
- package/dist/agents/image/image.types.js +6 -0
- package/dist/agents/image/image.types.js.map +1 -0
- package/{src/agents/image-agent.yaml → dist/agents/image/image.yaml} +21 -21
- package/dist/agents/image/index.d.ts +14 -0
- package/dist/agents/image/index.d.ts.map +1 -0
- package/dist/agents/image/index.js +19 -0
- package/dist/agents/image/index.js.map +1 -0
- package/dist/agents/index.d.ts +95 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +76 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/joker/index.d.ts +14 -0
- package/dist/agents/joker/index.d.ts.map +1 -0
- package/dist/agents/joker/index.js +19 -0
- package/dist/agents/joker/index.js.map +1 -0
- package/dist/agents/joker/joker.handler.d.ts +8 -0
- package/dist/agents/joker/joker.handler.d.ts.map +1 -0
- package/dist/agents/joker/joker.handler.js +48 -0
- package/dist/agents/joker/joker.handler.js.map +1 -0
- package/dist/agents/joker/joker.schema.d.ts +12 -0
- package/dist/agents/joker/joker.schema.d.ts.map +1 -0
- package/dist/agents/joker/joker.schema.js +13 -0
- package/dist/agents/joker/joker.schema.js.map +1 -0
- package/dist/agents/joker/joker.types.d.ts +35 -0
- package/dist/agents/joker/joker.types.d.ts.map +1 -0
- package/dist/agents/joker/joker.types.js +6 -0
- package/dist/agents/joker/joker.types.js.map +1 -0
- package/{src/agents/joker-agent.yaml → dist/agents/joker/joker.yaml} +4 -4
- package/dist/agents/mcp-tool/index.d.ts +14 -0
- package/dist/agents/mcp-tool/index.d.ts.map +1 -0
- package/dist/agents/mcp-tool/index.js +19 -0
- package/dist/agents/mcp-tool/index.js.map +1 -0
- package/dist/agents/mcp-tool/mcp-tool.handler.d.ts +12 -0
- package/dist/agents/mcp-tool/mcp-tool.handler.d.ts.map +1 -0
- package/dist/agents/mcp-tool/mcp-tool.handler.js +116 -0
- package/dist/agents/mcp-tool/mcp-tool.handler.js.map +1 -0
- package/dist/agents/mcp-tool/mcp-tool.schema.d.ts +19 -0
- package/dist/agents/mcp-tool/mcp-tool.schema.d.ts.map +1 -0
- package/dist/agents/mcp-tool/mcp-tool.schema.js +20 -0
- package/dist/agents/mcp-tool/mcp-tool.schema.js.map +1 -0
- package/dist/agents/mcp-tool/mcp-tool.types.d.ts +31 -0
- package/dist/agents/mcp-tool/mcp-tool.types.d.ts.map +1 -0
- package/dist/agents/mcp-tool/mcp-tool.types.js +6 -0
- package/dist/agents/mcp-tool/mcp-tool.types.js.map +1 -0
- package/dist/agents/mcp-tool/mcp-tool.yaml +71 -0
- package/dist/agents/rag/index.d.ts +15 -0
- package/dist/agents/rag/index.d.ts.map +1 -0
- package/dist/agents/rag/index.js +20 -0
- package/dist/agents/rag/index.js.map +1 -0
- package/dist/agents/rag/rag.handler.d.ts +8 -0
- package/dist/agents/rag/rag.handler.d.ts.map +1 -0
- package/dist/agents/rag/rag.handler.js +101 -0
- package/dist/agents/rag/rag.handler.js.map +1 -0
- package/dist/agents/rag/rag.schema.d.ts +27 -0
- package/dist/agents/rag/rag.schema.d.ts.map +1 -0
- package/dist/agents/rag/rag.schema.js +24 -0
- package/dist/agents/rag/rag.schema.js.map +1 -0
- package/dist/agents/rag/rag.types.d.ts +47 -0
- package/dist/agents/rag/rag.types.d.ts.map +1 -0
- package/dist/agents/rag/rag.types.js +6 -0
- package/dist/agents/rag/rag.types.js.map +1 -0
- package/dist/agents/rag/rag.yaml +89 -0
- package/dist/agents/{agentRegistry.d.ts → registry/agentRegistry.d.ts} +25 -1
- package/dist/agents/registry/agentRegistry.d.ts.map +1 -0
- package/dist/agents/{agentRegistry.js → registry/agentRegistry.js} +154 -4
- package/dist/agents/registry/agentRegistry.js.map +1 -0
- package/dist/agents/registry/index.d.ts +6 -0
- package/dist/agents/registry/index.d.ts.map +1 -0
- package/dist/agents/registry/index.js +10 -0
- package/dist/agents/registry/index.js.map +1 -0
- package/dist/agents/translator/index.d.ts +14 -0
- package/dist/agents/translator/index.d.ts.map +1 -0
- package/dist/agents/translator/index.js +19 -0
- package/dist/agents/translator/index.js.map +1 -0
- package/dist/agents/translator/translator.handler.d.ts +8 -0
- package/dist/agents/translator/translator.handler.d.ts.map +1 -0
- package/dist/agents/translator/translator.handler.js +83 -0
- package/dist/agents/translator/translator.handler.js.map +1 -0
- package/dist/agents/translator/translator.schema.d.ts +27 -0
- package/dist/agents/translator/translator.schema.d.ts.map +1 -0
- package/dist/agents/translator/translator.schema.js +28 -0
- package/dist/agents/translator/translator.schema.js.map +1 -0
- package/dist/agents/translator/translator.types.d.ts +40 -0
- package/dist/agents/translator/translator.types.d.ts.map +1 -0
- package/dist/agents/translator/translator.types.js +6 -0
- package/dist/agents/translator/translator.types.js.map +1 -0
- package/{src/agents/translator-agent.yaml → dist/agents/translator/translator.yaml} +27 -27
- package/dist/client/index.d.ts +89 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +93 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +17 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +7 -0
- package/dist/client/types.js.map +1 -0
- package/dist/firebase/tenantManager.d.ts +34 -2
- package/dist/firebase/tenantManager.d.ts.map +1 -1
- package/dist/firebase/tenantManager.js +67 -1
- package/dist/firebase/tenantManager.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -7
- package/dist/index.js.map +1 -1
- package/dist/runtime/declarativeAgentRuntime.d.ts +14 -49
- package/dist/runtime/declarativeAgentRuntime.d.ts.map +1 -1
- package/dist/runtime/declarativeAgentRuntime.js +248 -355
- package/dist/runtime/declarativeAgentRuntime.js.map +1 -1
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +33 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/workflowExecutor.d.ts +30 -0
- package/dist/runtime/workflowExecutor.d.ts.map +1 -0
- package/dist/runtime/workflowExecutor.js +70 -0
- package/dist/runtime/workflowExecutor.js.map +1 -0
- package/dist/server/api/graphql.d.ts +1 -1
- package/dist/server/api/graphql.d.ts.map +1 -1
- package/dist/server/api/graphql.js +104 -62
- package/dist/server/api/graphql.js.map +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/shared/index.d.ts +7 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +23 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/types/agent.types.d.ts +50 -0
- package/dist/shared/types/agent.types.d.ts.map +1 -0
- package/dist/shared/types/agent.types.js +7 -0
- package/dist/shared/types/agent.types.js.map +1 -0
- package/dist/shared/types/execution.types.d.ts +42 -0
- package/dist/shared/types/execution.types.d.ts.map +1 -0
- package/dist/shared/types/execution.types.js +7 -0
- package/dist/shared/types/execution.types.js.map +1 -0
- package/dist/shared/types/index.d.ts +7 -0
- package/dist/shared/types/index.d.ts.map +1 -0
- package/dist/shared/types/index.js +23 -0
- package/dist/shared/types/index.js.map +1 -0
- package/dist/shared/types/schema.types.d.ts +52 -0
- package/dist/shared/types/schema.types.d.ts.map +1 -0
- package/dist/shared/types/schema.types.js +7 -0
- package/dist/shared/types/schema.types.js.map +1 -0
- package/dist/shared/utils/index.d.ts +5 -0
- package/dist/shared/utils/index.d.ts.map +1 -0
- package/dist/shared/utils/index.js +21 -0
- package/dist/shared/utils/index.js.map +1 -0
- package/dist/shared/utils/validation.d.ts +42 -0
- package/dist/shared/utils/validation.d.ts.map +1 -0
- package/dist/shared/utils/validation.js +93 -0
- package/dist/shared/utils/validation.js.map +1 -0
- package/dist/tenant/TenantManager.d.ts +152 -0
- package/dist/tenant/TenantManager.d.ts.map +1 -0
- package/dist/tenant/TenantManager.js +392 -0
- package/dist/tenant/TenantManager.js.map +1 -0
- package/dist/tenant/index.d.ts +47 -0
- package/dist/tenant/index.d.ts.map +1 -0
- package/dist/tenant/index.js +74 -0
- package/dist/tenant/index.js.map +1 -0
- package/dist/tenant/interfaces.d.ts +170 -0
- package/dist/tenant/interfaces.d.ts.map +1 -0
- package/dist/tenant/interfaces.js +67 -0
- package/dist/tenant/interfaces.js.map +1 -0
- package/dist/tenant/providerFactory.d.ts +43 -0
- package/dist/tenant/providerFactory.d.ts.map +1 -0
- package/dist/tenant/providerFactory.js +70 -0
- package/dist/tenant/providerFactory.js.map +1 -0
- package/dist/tenant/providerRegistry.d.ts +47 -0
- package/dist/tenant/providerRegistry.d.ts.map +1 -0
- package/dist/tenant/providerRegistry.js +79 -0
- package/dist/tenant/providerRegistry.js.map +1 -0
- package/dist/tenant/providers/FirebaseTenantProvider.d.ts +41 -0
- package/dist/tenant/providers/FirebaseTenantProvider.d.ts.map +1 -0
- package/dist/tenant/providers/FirebaseTenantProvider.js +290 -0
- package/dist/tenant/providers/FirebaseTenantProvider.js.map +1 -0
- package/dist/tenant/providers/InMemoryTenantProvider.d.ts +18 -0
- package/dist/tenant/providers/InMemoryTenantProvider.d.ts.map +1 -0
- package/dist/tenant/providers/InMemoryTenantProvider.js +137 -0
- package/dist/tenant/providers/InMemoryTenantProvider.js.map +1 -0
- package/package.json +48 -12
- package/src/agents/chat/chat.handler.ts +209 -0
- package/src/agents/chat/chat.schema.ts +33 -0
- package/src/agents/chat/chat.types.ts +46 -0
- package/src/agents/chat/chat.yaml +150 -0
- package/src/agents/chat/index.ts +21 -0
- package/src/agents/chromadb/chromadb.handler.ts +130 -0
- package/src/agents/chromadb/chromadb.schema.ts +35 -0
- package/src/agents/chromadb/chromadb.types.ts +52 -0
- package/src/agents/chromadb/chromadb.yaml +128 -0
- package/src/agents/chromadb/index.ts +20 -0
- package/src/agents/gemini-vectorize/gemini-vectorize.handler.ts +72 -0
- package/src/agents/gemini-vectorize/gemini-vectorize.schema.ts +22 -0
- package/src/agents/gemini-vectorize/gemini-vectorize.types.ts +34 -0
- package/src/agents/gemini-vectorize/gemini-vectorize.yaml +84 -0
- package/src/agents/gemini-vectorize/index.ts +20 -0
- package/src/agents/gitmcp/gitmcp.handler.ts +122 -0
- package/src/agents/gitmcp/gitmcp.schema.ts +20 -0
- package/src/agents/gitmcp/gitmcp.types.ts +33 -0
- package/src/agents/gitmcp/gitmcp.yaml +71 -0
- package/src/agents/gitmcp/index.ts +21 -0
- package/src/agents/image/image.handler.ts +82 -0
- package/src/agents/image/image.schema.ts +28 -0
- package/src/agents/image/image.types.ts +45 -0
- package/src/agents/image/image.yaml +86 -0
- package/src/agents/image/index.ts +19 -0
- package/src/agents/index.ts +59 -0
- package/src/agents/joker/index.ts +19 -0
- package/src/agents/joker/joker.handler.ts +60 -0
- package/src/agents/joker/joker.schema.ts +15 -0
- package/src/agents/joker/joker.types.ts +37 -0
- package/src/agents/joker/joker.yaml +47 -0
- package/src/agents/mcp-tool/index.ts +19 -0
- package/src/agents/mcp-tool/mcp-tool.handler.ts +112 -0
- package/src/agents/mcp-tool/mcp-tool.schema.ts +22 -0
- package/src/agents/mcp-tool/mcp-tool.types.ts +33 -0
- package/src/agents/mcp-tool/mcp-tool.yaml +71 -0
- package/src/agents/rag/index.ts +20 -0
- package/src/agents/rag/rag.handler.ts +119 -0
- package/src/agents/rag/rag.schema.ts +26 -0
- package/src/agents/rag/rag.types.ts +51 -0
- package/src/agents/rag/rag.yaml +89 -0
- package/src/agents/{agentRegistry.ts → registry/agentRegistry.ts} +161 -5
- package/src/agents/registry/index.ts +6 -0
- package/src/agents/translator/index.ts +19 -0
- package/src/agents/translator/translator.handler.ts +99 -0
- package/src/agents/translator/translator.schema.ts +30 -0
- package/src/agents/translator/translator.types.ts +42 -0
- package/src/agents/translator/translator.yaml +80 -0
- package/src/client/index.ts +53 -0
- package/src/client/types.ts +38 -0
- package/src/index.ts +48 -5
- package/src/runtime/declarativeAgentRuntime.ts +367 -489
- package/src/runtime/index.ts +31 -0
- package/src/runtime/workflowExecutor.ts +94 -0
- package/src/server/api/graphql.ts +109 -74
- package/src/server/index.ts +2 -2
- package/src/shared/index.ts +7 -0
- package/src/shared/types/agent.types.ts +80 -0
- package/src/shared/types/execution.types.ts +45 -0
- package/src/shared/types/index.ts +7 -0
- package/src/shared/types/schema.types.ts +55 -0
- package/src/shared/utils/index.ts +5 -0
- package/src/shared/utils/validation.ts +100 -0
- package/src/tenant/TenantManager.ts +488 -0
- package/src/tenant/index.ts +101 -0
- package/src/tenant/interfaces.ts +231 -0
- package/src/tenant/providerFactory.ts +75 -0
- package/src/tenant/providerRegistry.ts +86 -0
- package/src/tenant/providers/InMemoryTenantProvider.ts +168 -0
- package/dist/agents/agentRegistry.d.ts.map +0 -1
- package/dist/agents/agentRegistry.js.map +0 -1
- package/src/firebase/tenantManager.ts +0 -443
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Module - Server-only exports
|
|
3
|
+
*
|
|
4
|
+
* This module provides the declarative agent runtime and workflow execution.
|
|
5
|
+
* All exports in this module are server-only.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Main runtime exports
|
|
9
|
+
export { DeclarativeAgentInterpreter, declarativeInterpreter } from './declarativeAgentRuntime';
|
|
10
|
+
export type { YamlAgentDefinition, YamlAgentInterpreterOptions, YamlExecutionResult } from './declarativeAgentRuntime';
|
|
11
|
+
|
|
12
|
+
// Workflow executor exports
|
|
13
|
+
export {
|
|
14
|
+
executeWorkflowStep,
|
|
15
|
+
getAvailableStepTypes,
|
|
16
|
+
isStepTypeSupported,
|
|
17
|
+
// Individual handlers for direct use
|
|
18
|
+
executeJokeHandler,
|
|
19
|
+
executeTranslationHandler,
|
|
20
|
+
executeImageHandler,
|
|
21
|
+
executeMcpToolHandler,
|
|
22
|
+
executeVectorizeHandler,
|
|
23
|
+
executeChromaDBHandler,
|
|
24
|
+
executeGitMcpHandler,
|
|
25
|
+
executeRagHandler,
|
|
26
|
+
executeChatHandler,
|
|
27
|
+
} from './workflowExecutor';
|
|
28
|
+
|
|
29
|
+
// Schema compiler exports
|
|
30
|
+
export { DeclarativeSchemaCompiler, DeclarativeSchemaValidationError } from './schemaCompiler';
|
|
31
|
+
export type { DeclarativeSchemaPhase } from './schemaCompiler';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Workflow Executor - Server-only workflow step execution
|
|
5
|
+
* Delegates to individual agent handlers based on step type
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ExecutionContext } from '../types/executionContext';
|
|
9
|
+
import type { WorkflowStepType } from '../shared/types/agent.types';
|
|
10
|
+
|
|
11
|
+
// Import handlers from each agent
|
|
12
|
+
import { executeJokeHandler } from '../agents/joker/joker.handler';
|
|
13
|
+
import { executeTranslationHandler } from '../agents/translator/translator.handler';
|
|
14
|
+
import { executeImageHandler } from '../agents/image/image.handler';
|
|
15
|
+
import { executeMcpToolHandler } from '../agents/mcp-tool/mcp-tool.handler';
|
|
16
|
+
import { executeVectorizeHandler } from '../agents/gemini-vectorize/gemini-vectorize.handler';
|
|
17
|
+
import { executeChromaDBHandler } from '../agents/chromadb/chromadb.handler';
|
|
18
|
+
import { executeGitMcpHandler } from '../agents/gitmcp/gitmcp.handler';
|
|
19
|
+
import { executeRagHandler } from '../agents/rag/rag.handler';
|
|
20
|
+
import { executeChatHandler } from '../agents/chat/chat.handler';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Handler function type - uses any for params to allow flexible handler signatures
|
|
24
|
+
*/
|
|
25
|
+
type HandlerFunction = (
|
|
26
|
+
params: any,
|
|
27
|
+
props: Record<string, string>,
|
|
28
|
+
context: ExecutionContext
|
|
29
|
+
) => Promise<unknown>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Map of workflow step types to their handlers
|
|
33
|
+
* Maps both legacy (Portuguese) and new (English) step type names
|
|
34
|
+
*/
|
|
35
|
+
const handlerMap: Record<string, HandlerFunction> = {
|
|
36
|
+
// English step types (preferred)
|
|
37
|
+
'joke': executeJokeHandler,
|
|
38
|
+
'translation': executeTranslationHandler,
|
|
39
|
+
'image': executeImageHandler,
|
|
40
|
+
'mcp-tool': executeMcpToolHandler,
|
|
41
|
+
'vectorize': executeVectorizeHandler,
|
|
42
|
+
'chromadb': executeChromaDBHandler,
|
|
43
|
+
'gitmcp': executeGitMcpHandler,
|
|
44
|
+
'rag': executeRagHandler,
|
|
45
|
+
'chat': executeChatHandler,
|
|
46
|
+
// Legacy step types (for backward compatibility)
|
|
47
|
+
'genkit-joke': executeJokeHandler,
|
|
48
|
+
'genkit-translation': executeTranslationHandler,
|
|
49
|
+
'genkit-image': executeImageHandler,
|
|
50
|
+
'gemini-vectorize': executeVectorizeHandler,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Execute a workflow step by delegating to the appropriate handler
|
|
55
|
+
*/
|
|
56
|
+
export async function executeWorkflowStep(
|
|
57
|
+
stepType: WorkflowStepType | string,
|
|
58
|
+
params: Record<string, unknown>,
|
|
59
|
+
props: Record<string, string>,
|
|
60
|
+
context: ExecutionContext
|
|
61
|
+
): Promise<unknown> {
|
|
62
|
+
const handler = handlerMap[stepType];
|
|
63
|
+
if (!handler) {
|
|
64
|
+
throw new Error(`Unknown workflow step type: ${stepType}`);
|
|
65
|
+
}
|
|
66
|
+
return handler(params, props, context);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get all available workflow step types
|
|
71
|
+
*/
|
|
72
|
+
export function getAvailableStepTypes(): string[] {
|
|
73
|
+
return Object.keys(handlerMap);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if a step type is supported
|
|
78
|
+
*/
|
|
79
|
+
export function isStepTypeSupported(stepType: string): boolean {
|
|
80
|
+
return stepType in handlerMap;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Export individual handlers for direct use
|
|
84
|
+
export {
|
|
85
|
+
executeJokeHandler,
|
|
86
|
+
executeTranslationHandler,
|
|
87
|
+
executeImageHandler,
|
|
88
|
+
executeMcpToolHandler,
|
|
89
|
+
executeVectorizeHandler,
|
|
90
|
+
executeChromaDBHandler,
|
|
91
|
+
executeGitMcpHandler,
|
|
92
|
+
executeRagHandler,
|
|
93
|
+
executeChatHandler,
|
|
94
|
+
};
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* GraphQL helpers used by the /api/graphql route.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { GraphQLError, GraphQLScalarType, Kind, type ValueNode } from "graphql";
|
|
6
|
+
import { createSchema, createYoga } from "graphql-yoga";
|
|
7
|
+
import { agentRegistry } from "../../agents/registry";
|
|
6
8
|
import {
|
|
7
9
|
getClientByApiKey,
|
|
8
10
|
getEndpointByName,
|
|
@@ -39,6 +41,39 @@ export function getGraphQLSchema(): string {
|
|
|
39
41
|
return schema;
|
|
40
42
|
}
|
|
41
43
|
|
|
44
|
+
const parseJsonLiteral = (ast: ValueNode): unknown => {
|
|
45
|
+
switch (ast.kind) {
|
|
46
|
+
case Kind.STRING:
|
|
47
|
+
case Kind.BOOLEAN:
|
|
48
|
+
return ast.value;
|
|
49
|
+
case Kind.INT:
|
|
50
|
+
return parseInt(ast.value, 10);
|
|
51
|
+
case Kind.FLOAT:
|
|
52
|
+
return parseFloat(ast.value);
|
|
53
|
+
case Kind.OBJECT: {
|
|
54
|
+
const value: Record<string, any> = {};
|
|
55
|
+
for (const field of ast.fields) {
|
|
56
|
+
value[field.name.value] = parseJsonLiteral(field.value);
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
case Kind.LIST:
|
|
61
|
+
return ast.values.map(parseJsonLiteral);
|
|
62
|
+
case Kind.NULL:
|
|
63
|
+
return null;
|
|
64
|
+
default:
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const jsonScalar = new GraphQLScalarType({
|
|
70
|
+
name: "JSON",
|
|
71
|
+
description: "Arbitrary JSON value",
|
|
72
|
+
serialize: (value: unknown) => value,
|
|
73
|
+
parseValue: (value: unknown) => value,
|
|
74
|
+
parseLiteral: (ast: ValueNode) => parseJsonLiteral(ast),
|
|
75
|
+
});
|
|
76
|
+
|
|
42
77
|
export async function executeRegisteredMethod(
|
|
43
78
|
input: ExecuteMethodInput,
|
|
44
79
|
clientId: string
|
|
@@ -164,86 +199,86 @@ export async function executeRegisteredMethod(
|
|
|
164
199
|
}
|
|
165
200
|
}
|
|
166
201
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
let clientId: string;
|
|
170
|
-
const authHeader = request.headers.get("authorization");
|
|
202
|
+
async function resolveClientId(request: Request): Promise<string> {
|
|
203
|
+
const authHeader = request.headers.get("authorization");
|
|
171
204
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
const client = await getClientByApiKey(apiKey);
|
|
178
|
-
if (!client) throw new AuthenticationError("Invalid API key");
|
|
179
|
-
const rateLimitOk = await checkRateLimit(client.id, client.rateLimit);
|
|
180
|
-
if (!rateLimitOk) throw new RateLimitError("Rate limit exceeded.");
|
|
181
|
-
clientId = client.id;
|
|
182
|
-
} else if (request.headers.get("x-admin-tenant") === "true") {
|
|
183
|
-
clientId = "admin_tenant";
|
|
184
|
-
} else {
|
|
185
|
-
throw new AuthenticationError(
|
|
186
|
-
"Missing or invalid authorization header"
|
|
187
|
-
);
|
|
205
|
+
if (authHeader && authHeader.startsWith("Bearer ")) {
|
|
206
|
+
const apiKey = authHeader.substring(7);
|
|
207
|
+
if (!isValidApiKey(apiKey)) {
|
|
208
|
+
throw new AuthenticationError("Invalid API key format");
|
|
188
209
|
}
|
|
210
|
+
const client = await getClientByApiKey(apiKey);
|
|
211
|
+
if (!client) throw new AuthenticationError("Invalid API key");
|
|
212
|
+
const rateLimitOk = await checkRateLimit(client.id, client.rateLimit);
|
|
213
|
+
if (!rateLimitOk) throw new RateLimitError("Rate limit exceeded.");
|
|
214
|
+
return client.id;
|
|
215
|
+
}
|
|
189
216
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
217
|
+
if (request.headers.get("x-admin-tenant") === "true") {
|
|
218
|
+
return "admin_tenant";
|
|
219
|
+
}
|
|
194
220
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
throw new ValidationError(
|
|
198
|
-
"Missing 'variables' or 'methodName' in request body"
|
|
199
|
-
);
|
|
200
|
-
}
|
|
221
|
+
throw new AuthenticationError("Missing or invalid authorization header");
|
|
222
|
+
}
|
|
201
223
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
params: body.variables.params || {},
|
|
206
|
-
props: body.variables.props || {},
|
|
207
|
-
},
|
|
208
|
-
clientId
|
|
209
|
-
);
|
|
210
|
-
return Response.json({ data: { executeMethod: result } });
|
|
211
|
-
}
|
|
224
|
+
function toGraphQLError(error: unknown): GraphQLError {
|
|
225
|
+
const message = error instanceof Error ? error.message : "Internal server error";
|
|
226
|
+
let code = "INTERNAL_SERVER_ERROR";
|
|
212
227
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
: error instanceof RateLimitError
|
|
222
|
-
? 429
|
|
223
|
-
: error instanceof ValidationError
|
|
224
|
-
? 400
|
|
225
|
-
: error instanceof NotFoundError
|
|
226
|
-
? 404
|
|
227
|
-
: 500;
|
|
228
|
-
return Response.json(
|
|
229
|
-
{
|
|
230
|
-
errors: [
|
|
231
|
-
{
|
|
232
|
-
message:
|
|
233
|
-
error instanceof Error ? error.message : "Internal server error",
|
|
234
|
-
},
|
|
235
|
-
],
|
|
236
|
-
},
|
|
237
|
-
{ status }
|
|
238
|
-
);
|
|
228
|
+
if (error instanceof AuthenticationError) {
|
|
229
|
+
code = "UNAUTHENTICATED";
|
|
230
|
+
} else if (error instanceof RateLimitError) {
|
|
231
|
+
code = "RATE_LIMITED";
|
|
232
|
+
} else if (error instanceof ValidationError) {
|
|
233
|
+
code = "BAD_USER_INPUT";
|
|
234
|
+
} else if (error instanceof NotFoundError) {
|
|
235
|
+
code = "NOT_FOUND";
|
|
239
236
|
}
|
|
237
|
+
|
|
238
|
+
return new GraphQLError(message, { extensions: { code } });
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const yoga = createYoga({
|
|
242
|
+
schema: createSchema({
|
|
243
|
+
typeDefs: schema,
|
|
244
|
+
resolvers: {
|
|
245
|
+
JSON: jsonScalar,
|
|
246
|
+
Query: {
|
|
247
|
+
ping: () => "pong",
|
|
248
|
+
},
|
|
249
|
+
Mutation: {
|
|
250
|
+
executeMethod: async (
|
|
251
|
+
_parent: unknown,
|
|
252
|
+
args: { methodName: string; params?: Record<string, unknown>; props?: Record<string, string> },
|
|
253
|
+
context: { request: Request }
|
|
254
|
+
) => {
|
|
255
|
+
try {
|
|
256
|
+
const clientId = await resolveClientId(context.request);
|
|
257
|
+
return await executeRegisteredMethod(
|
|
258
|
+
{
|
|
259
|
+
methodName: args.methodName,
|
|
260
|
+
params: args.params || {},
|
|
261
|
+
props: args.props || {},
|
|
262
|
+
},
|
|
263
|
+
clientId
|
|
264
|
+
);
|
|
265
|
+
} catch (error) {
|
|
266
|
+
throw toGraphQLError(error);
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
}),
|
|
272
|
+
context: ({ request }: { request: Request }) => ({ request }),
|
|
273
|
+
graphqlEndpoint: "/api/graphql",
|
|
274
|
+
graphiql: true,
|
|
275
|
+
fetchAPI: { Request, Response },
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
export async function handleGraphQLPost(request: Request) {
|
|
279
|
+
return yoga.handleRequest(request, { request });
|
|
240
280
|
}
|
|
241
281
|
|
|
242
|
-
export function handleGraphQLGet() {
|
|
243
|
-
return
|
|
244
|
-
`<!DOCTYPE html>
|
|
245
|
-
<html><head><title>Opal Support API - GraphQL</title><style>body{font-family:sans-serif;max-width:800px;margin:50px auto;padding:20px}code,pre{background:#f4f4f4;padding:4px 8px;border-radius:4px}</style></head>
|
|
246
|
-
<body><h1>Opal Support API</h1><p>GraphQL endpoint for executing registered methods.</p><h2>Endpoint</h2><code>POST /api/graphql</code><h2>Authentication</h2><p>Use Bearer token in Authorization header.</p><h2>Schema</h2><pre>${schema}</pre></body></html>`,
|
|
247
|
-
{ headers: { "Content-Type": "text/html" } }
|
|
248
|
-
);
|
|
282
|
+
export async function handleGraphQLGet(request: Request) {
|
|
283
|
+
return yoga.handleRequest(request, { request });
|
|
249
284
|
}
|
package/src/server/index.ts
CHANGED
|
@@ -2,5 +2,5 @@ export * from "./types";
|
|
|
2
2
|
export * from "./errors";
|
|
3
3
|
export * from "./kvStore";
|
|
4
4
|
export * from "./runtimeSecurity";
|
|
5
|
-
export { agentRegistry } from "../agents/
|
|
6
|
-
export type { AgentRegistration } from "../agents/
|
|
5
|
+
export { agentRegistry } from "../agents/registry";
|
|
6
|
+
export type { AgentRegistration } from "../agents/registry";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Agent Types - Safe for client and server
|
|
3
|
+
* These types contain no sensitive data and can be used in both environments
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Agent metadata - safe for client display
|
|
8
|
+
*/
|
|
9
|
+
export interface AgentMetadata {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
category: string;
|
|
14
|
+
route: string;
|
|
15
|
+
tags?: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generic agent response wrapper
|
|
20
|
+
*/
|
|
21
|
+
export interface AgentResponse<T = unknown> {
|
|
22
|
+
success: boolean;
|
|
23
|
+
data?: T;
|
|
24
|
+
error?: string;
|
|
25
|
+
timestamp?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Execution step tracking for workflow visualization
|
|
30
|
+
*/
|
|
31
|
+
export interface ExecutionStep {
|
|
32
|
+
agent: string;
|
|
33
|
+
action: string;
|
|
34
|
+
status: 'running' | 'success' | 'error';
|
|
35
|
+
startTime: number;
|
|
36
|
+
endTime?: number;
|
|
37
|
+
duration?: number;
|
|
38
|
+
input?: Record<string, unknown>;
|
|
39
|
+
output?: Record<string, unknown>;
|
|
40
|
+
error?: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
phase?: 'orchestration' | 'vectorization' | 'storage' | 'retrieval' | 'ingestion' | 'generation';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Workflow step types supported by the runtime
|
|
47
|
+
* Includes both English (preferred) and legacy (Portuguese) names
|
|
48
|
+
*/
|
|
49
|
+
export type WorkflowStepType =
|
|
50
|
+
// English step types (preferred)
|
|
51
|
+
| 'joke'
|
|
52
|
+
| 'translation'
|
|
53
|
+
| 'image'
|
|
54
|
+
| 'vectorize'
|
|
55
|
+
| 'mcp-tool'
|
|
56
|
+
| 'chromadb'
|
|
57
|
+
| 'gitmcp'
|
|
58
|
+
| 'rag'
|
|
59
|
+
| 'chat'
|
|
60
|
+
| 'output-generator'
|
|
61
|
+
| 'builtin-agent'
|
|
62
|
+
| 'custom-action'
|
|
63
|
+
// Legacy step types (backward compatibility)
|
|
64
|
+
| 'genkit-joke'
|
|
65
|
+
| 'genkit-translation'
|
|
66
|
+
| 'genkit-image'
|
|
67
|
+
| 'gemini-vectorize';
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Agent categories for organization
|
|
71
|
+
*/
|
|
72
|
+
export type AgentCategory =
|
|
73
|
+
| 'utility'
|
|
74
|
+
| 'translation'
|
|
75
|
+
| 'image'
|
|
76
|
+
| 'mcp'
|
|
77
|
+
| 'vectorization'
|
|
78
|
+
| 'storage'
|
|
79
|
+
| 'retrieval'
|
|
80
|
+
| 'orchestration';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Types - Shared between client and server
|
|
3
|
+
* Used for tracking and displaying execution progress
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Execution result from a workflow step
|
|
8
|
+
*/
|
|
9
|
+
export interface ExecutionResult<T = unknown> {
|
|
10
|
+
success: boolean;
|
|
11
|
+
data?: T;
|
|
12
|
+
error?: string;
|
|
13
|
+
duration?: number;
|
|
14
|
+
metadata?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Workflow execution status
|
|
19
|
+
*/
|
|
20
|
+
export type ExecutionStatus = 'pending' | 'running' | 'success' | 'error' | 'cancelled';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Workflow execution summary
|
|
24
|
+
*/
|
|
25
|
+
export interface ExecutionSummary {
|
|
26
|
+
agentId: string;
|
|
27
|
+
status: ExecutionStatus;
|
|
28
|
+
startTime: number;
|
|
29
|
+
endTime?: number;
|
|
30
|
+
totalDuration?: number;
|
|
31
|
+
stepsCompleted: number;
|
|
32
|
+
totalSteps: number;
|
|
33
|
+
error?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Execution log entry
|
|
38
|
+
*/
|
|
39
|
+
export interface ExecutionLogEntry {
|
|
40
|
+
timestamp: number;
|
|
41
|
+
level: 'info' | 'warn' | 'error' | 'debug';
|
|
42
|
+
message: string;
|
|
43
|
+
step?: string;
|
|
44
|
+
metadata?: Record<string, unknown>;
|
|
45
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Types - Shared type definitions for agent schemas
|
|
3
|
+
* Used for input/output validation on both client and server
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* JSON Schema-like type definition
|
|
8
|
+
*/
|
|
9
|
+
export interface SchemaProperty {
|
|
10
|
+
type: 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
11
|
+
description?: string;
|
|
12
|
+
enum?: string[];
|
|
13
|
+
items?: SchemaProperty;
|
|
14
|
+
properties?: Record<string, SchemaProperty>;
|
|
15
|
+
required?: string[];
|
|
16
|
+
default?: unknown;
|
|
17
|
+
minLength?: number;
|
|
18
|
+
maxLength?: number;
|
|
19
|
+
minimum?: number;
|
|
20
|
+
maximum?: number;
|
|
21
|
+
pattern?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Agent schema definition
|
|
26
|
+
*/
|
|
27
|
+
export interface AgentSchemaDefinition {
|
|
28
|
+
input: {
|
|
29
|
+
type: 'object';
|
|
30
|
+
properties: Record<string, SchemaProperty>;
|
|
31
|
+
required?: string[];
|
|
32
|
+
};
|
|
33
|
+
output: {
|
|
34
|
+
type: 'object';
|
|
35
|
+
properties: Record<string, SchemaProperty>;
|
|
36
|
+
required?: string[];
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Validation result
|
|
42
|
+
*/
|
|
43
|
+
export interface ValidationResult {
|
|
44
|
+
valid: boolean;
|
|
45
|
+
errors?: ValidationError[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Validation error detail
|
|
50
|
+
*/
|
|
51
|
+
export interface ValidationError {
|
|
52
|
+
path: string;
|
|
53
|
+
message: string;
|
|
54
|
+
code: string;
|
|
55
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Utilities - Shared validation helpers
|
|
3
|
+
* Safe for use in both client and server environments
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ValidationResult, ValidationError } from '../types/schema.types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Validate that a value is a non-empty string
|
|
10
|
+
*/
|
|
11
|
+
export function isNonEmptyString(value: unknown): value is string {
|
|
12
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Validate that a value is a positive number
|
|
17
|
+
*/
|
|
18
|
+
export function isPositiveNumber(value: unknown): value is number {
|
|
19
|
+
return typeof value === 'number' && value > 0 && !isNaN(value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Validate that a value is a valid URL
|
|
24
|
+
*/
|
|
25
|
+
export function isValidUrl(value: unknown): value is string {
|
|
26
|
+
if (typeof value !== 'string') return false;
|
|
27
|
+
try {
|
|
28
|
+
new URL(value);
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Validate resolution format (e.g., "1024x1024")
|
|
37
|
+
*/
|
|
38
|
+
export function isValidResolution(value: unknown): value is string {
|
|
39
|
+
if (typeof value !== 'string') return false;
|
|
40
|
+
return /^\d+x\d+$/.test(value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Validate language code (e.g., "en", "pt", "es")
|
|
45
|
+
*/
|
|
46
|
+
export function isValidLanguageCode(value: unknown): value is string {
|
|
47
|
+
if (typeof value !== 'string') return false;
|
|
48
|
+
return /^[a-z]{2}(-[A-Z]{2})?$/.test(value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create a validation result with errors
|
|
53
|
+
*/
|
|
54
|
+
export function createValidationResult(errors: ValidationError[]): ValidationResult {
|
|
55
|
+
return {
|
|
56
|
+
valid: errors.length === 0,
|
|
57
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create a validation error
|
|
63
|
+
*/
|
|
64
|
+
export function createValidationError(
|
|
65
|
+
path: string,
|
|
66
|
+
message: string,
|
|
67
|
+
code: string
|
|
68
|
+
): ValidationError {
|
|
69
|
+
return { path, message, code };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sanitize string input by trimming whitespace
|
|
74
|
+
*/
|
|
75
|
+
export function sanitizeString(value: unknown): string {
|
|
76
|
+
if (typeof value !== 'string') return '';
|
|
77
|
+
return value.trim();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Validate required fields in an object
|
|
82
|
+
*/
|
|
83
|
+
export function validateRequiredFields(
|
|
84
|
+
obj: Record<string, unknown>,
|
|
85
|
+
requiredFields: string[]
|
|
86
|
+
): ValidationError[] {
|
|
87
|
+
const errors: ValidationError[] = [];
|
|
88
|
+
|
|
89
|
+
for (const field of requiredFields) {
|
|
90
|
+
if (obj[field] === undefined || obj[field] === null) {
|
|
91
|
+
errors.push(createValidationError(
|
|
92
|
+
field,
|
|
93
|
+
`Missing required field: ${field}`,
|
|
94
|
+
'REQUIRED_FIELD_MISSING'
|
|
95
|
+
));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return errors;
|
|
100
|
+
}
|