beddel 0.1.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/README.md +297 -0
- package/dist/agents/agentRegistry.d.ts +68 -0
- package/dist/agents/agentRegistry.d.ts.map +1 -0
- package/dist/agents/agentRegistry.js +222 -0
- package/dist/agents/agentRegistry.js.map +1 -0
- package/dist/agents/formatter-agent.d.ts +10 -0
- package/dist/agents/formatter-agent.d.ts.map +1 -0
- package/dist/agents/formatter-agent.js +49 -0
- package/dist/agents/formatter-agent.js.map +1 -0
- package/dist/agents/genkit-agent.d.ts +12 -0
- package/dist/agents/genkit-agent.d.ts.map +1 -0
- package/dist/agents/genkit-agent.js +119 -0
- package/dist/agents/genkit-agent.js.map +1 -0
- package/dist/agents/i18n-messages.d.ts +17 -0
- package/dist/agents/i18n-messages.d.ts.map +1 -0
- package/dist/agents/i18n-messages.js +92 -0
- package/dist/agents/i18n-messages.js.map +1 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +26 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/pipeline.d.ts +15 -0
- package/dist/agents/pipeline.d.ts.map +1 -0
- package/dist/agents/pipeline.js +45 -0
- package/dist/agents/pipeline.js.map +1 -0
- package/dist/agents/schema-factory.d.ts +40 -0
- package/dist/agents/schema-factory.d.ts.map +1 -0
- package/dist/agents/schema-factory.js +121 -0
- package/dist/agents/schema-factory.js.map +1 -0
- package/dist/agents/translation-validators.d.ts +26 -0
- package/dist/agents/translation-validators.d.ts.map +1 -0
- package/dist/agents/translation-validators.js +77 -0
- package/dist/agents/translation-validators.js.map +1 -0
- package/dist/agents/translator-agents.d.ts +184 -0
- package/dist/agents/translator-agents.d.ts.map +1 -0
- package/dist/agents/translator-agents.js +613 -0
- package/dist/agents/translator-agents.js.map +1 -0
- package/dist/agents/types/translation.types.d.ts +100 -0
- package/dist/agents/types/translation.types.d.ts.map +1 -0
- package/dist/agents/types/translation.types.js +3 -0
- package/dist/agents/types/translation.types.js.map +1 -0
- package/dist/agents/validator-agent.d.ts +42 -0
- package/dist/agents/validator-agent.d.ts.map +1 -0
- package/dist/agents/validator-agent.js +122 -0
- package/dist/agents/validator-agent.js.map +1 -0
- package/dist/audit/auditTrail.d.ts +55 -0
- package/dist/audit/auditTrail.d.ts.map +1 -0
- package/dist/audit/auditTrail.js +93 -0
- package/dist/audit/auditTrail.js.map +1 -0
- package/dist/compliance/gdprEngine.d.ts +44 -0
- package/dist/compliance/gdprEngine.d.ts.map +1 -0
- package/dist/compliance/gdprEngine.js +178 -0
- package/dist/compliance/gdprEngine.js.map +1 -0
- package/dist/compliance/lgpdEngine.d.ts +51 -0
- package/dist/compliance/lgpdEngine.d.ts.map +1 -0
- package/dist/compliance/lgpdEngine.js +221 -0
- package/dist/compliance/lgpdEngine.js.map +1 -0
- package/dist/config.d.ts +78 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +17 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +40 -0
- package/dist/errors.js.map +1 -0
- package/dist/firebase/tenantManager.d.ts +84 -0
- package/dist/firebase/tenantManager.d.ts.map +1 -0
- package/dist/firebase/tenantManager.js +378 -0
- package/dist/firebase/tenantManager.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/secure-yaml-runtime.d.ts +68 -0
- package/dist/integration/secure-yaml-runtime.d.ts.map +1 -0
- package/dist/integration/secure-yaml-runtime.js +245 -0
- package/dist/integration/secure-yaml-runtime.js.map +1 -0
- package/dist/parser/secure-yaml-parser.d.ts +62 -0
- package/dist/parser/secure-yaml-parser.d.ts.map +1 -0
- package/dist/parser/secure-yaml-parser.js +234 -0
- package/dist/parser/secure-yaml-parser.js.map +1 -0
- package/dist/performance/autoscaling.d.ts +100 -0
- package/dist/performance/autoscaling.d.ts.map +1 -0
- package/dist/performance/autoscaling.js +339 -0
- package/dist/performance/autoscaling.js.map +1 -0
- package/dist/performance/benchmark.d.ts +104 -0
- package/dist/performance/benchmark.d.ts.map +1 -0
- package/dist/performance/benchmark.js +514 -0
- package/dist/performance/benchmark.js.map +1 -0
- package/dist/performance/index.d.ts +14 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/index.js +35 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/monitor.d.ts +126 -0
- package/dist/performance/monitor.d.ts.map +1 -0
- package/dist/performance/monitor.js +324 -0
- package/dist/performance/monitor.js.map +1 -0
- package/dist/performance/streaming.d.ts +82 -0
- package/dist/performance/streaming.d.ts.map +1 -0
- package/dist/performance/streaming.js +287 -0
- package/dist/performance/streaming.js.map +1 -0
- package/dist/runtime/audit.d.ts +240 -0
- package/dist/runtime/audit.d.ts.map +1 -0
- package/dist/runtime/audit.js +641 -0
- package/dist/runtime/audit.js.map +1 -0
- package/dist/runtime/declarativeAgentRuntime.d.ts +123 -0
- package/dist/runtime/declarativeAgentRuntime.d.ts.map +1 -0
- package/dist/runtime/declarativeAgentRuntime.js +576 -0
- package/dist/runtime/declarativeAgentRuntime.js.map +1 -0
- package/dist/runtime/isolatedRuntime.d.ts +119 -0
- package/dist/runtime/isolatedRuntime.d.ts.map +1 -0
- package/dist/runtime/isolatedRuntime.js +425 -0
- package/dist/runtime/isolatedRuntime.js.map +1 -0
- package/dist/runtime/schemaCompiler.d.ts +35 -0
- package/dist/runtime/schemaCompiler.d.ts.map +1 -0
- package/dist/runtime/schemaCompiler.js +151 -0
- package/dist/runtime/schemaCompiler.js.map +1 -0
- package/dist/runtime/simpleRuntime.d.ts +57 -0
- package/dist/runtime/simpleRuntime.d.ts.map +1 -0
- package/dist/runtime/simpleRuntime.js +187 -0
- package/dist/runtime/simpleRuntime.js.map +1 -0
- package/dist/security/dashboard.d.ts +89 -0
- package/dist/security/dashboard.d.ts.map +1 -0
- package/dist/security/dashboard.js +300 -0
- package/dist/security/dashboard.js.map +1 -0
- package/dist/security/hardening.d.ts +130 -0
- package/dist/security/hardening.d.ts.map +1 -0
- package/dist/security/hardening.js +414 -0
- package/dist/security/hardening.js.map +1 -0
- package/dist/security/index.d.ts +128 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +353 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/monitor.d.ts +88 -0
- package/dist/security/monitor.d.ts.map +1 -0
- package/dist/security/monitor.js +356 -0
- package/dist/security/monitor.js.map +1 -0
- package/dist/security/scanner.d.ts +104 -0
- package/dist/security/scanner.d.ts.map +1 -0
- package/dist/security/scanner.js +298 -0
- package/dist/security/scanner.js.map +1 -0
- package/dist/security/score.d.ts +150 -0
- package/dist/security/score.d.ts.map +1 -0
- package/dist/security/score.js +983 -0
- package/dist/security/score.js.map +1 -0
- package/dist/security/test-security.d.ts +22 -0
- package/dist/security/test-security.d.ts.map +1 -0
- package/dist/security/test-security.js +154 -0
- package/dist/security/test-security.js.map +1 -0
- package/dist/security/threatDetector.d.ts +39 -0
- package/dist/security/threatDetector.d.ts.map +1 -0
- package/dist/security/threatDetector.js +354 -0
- package/dist/security/threatDetector.js.map +1 -0
- package/dist/security/validation.d.ts +69 -0
- package/dist/security/validation.d.ts.map +1 -0
- package/dist/security/validation.js +286 -0
- package/dist/security/validation.js.map +1 -0
- package/dist/server/api/clientsRoute.d.ts +9 -0
- package/dist/server/api/clientsRoute.d.ts.map +1 -0
- package/dist/server/api/clientsRoute.js +71 -0
- package/dist/server/api/clientsRoute.js.map +1 -0
- package/dist/server/api/endpointsRoute.d.ts +8 -0
- package/dist/server/api/endpointsRoute.d.ts.map +1 -0
- package/dist/server/api/endpointsRoute.js +76 -0
- package/dist/server/api/endpointsRoute.js.map +1 -0
- package/dist/server/api/graphql.d.ts +9 -0
- package/dist/server/api/graphql.d.ts.map +1 -0
- package/dist/server/api/graphql.js +180 -0
- package/dist/server/api/graphql.js.map +1 -0
- package/dist/server/errors.d.ts +19 -0
- package/dist/server/errors.d.ts.map +1 -0
- package/dist/server/errors.js +42 -0
- package/dist/server/errors.js.map +1 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +24 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/kvStore.d.ts +27 -0
- package/dist/server/kvStore.d.ts.map +1 -0
- package/dist/server/kvStore.js +128 -0
- package/dist/server/kvStore.js.map +1 -0
- package/dist/server/runtimeSecurity.d.ts +28 -0
- package/dist/server/runtimeSecurity.d.ts.map +1 -0
- package/dist/server/runtimeSecurity.js +85 -0
- package/dist/server/runtimeSecurity.js.map +1 -0
- package/dist/server/types.d.ts +53 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +8 -0
- package/dist/server/types.js.map +1 -0
- package/dist/types/executionContext.d.ts +16 -0
- package/dist/types/executionContext.d.ts.map +1 -0
- package/dist/types/executionContext.js +3 -0
- package/dist/types/executionContext.js.map +1 -0
- package/package.json +77 -0
- package/src/agents/agentRegistry.ts +272 -0
- package/src/agents/image-agent.yaml +86 -0
- package/src/agents/joker-agent.yaml +47 -0
- package/src/agents/translator-agent.yaml +80 -0
- package/src/audit/auditTrail.ts +134 -0
- package/src/compliance/gdprEngine.ts +209 -0
- package/src/compliance/lgpdEngine.ts +268 -0
- package/src/config.ts +179 -0
- package/src/errors.ts +35 -0
- package/src/firebase/tenantManager.ts +443 -0
- package/src/index.ts +125 -0
- package/src/integration/secure-yaml-runtime.ts +341 -0
- package/src/parser/secure-yaml-parser.ts +273 -0
- package/src/performance/autoscaling.ts +495 -0
- package/src/performance/benchmark.ts +644 -0
- package/src/performance/index.ts +34 -0
- package/src/performance/monitor.ts +469 -0
- package/src/performance/streaming.ts +317 -0
- package/src/runtime/audit.ts +907 -0
- package/src/runtime/declarativeAgentRuntime.ts +836 -0
- package/src/runtime/isolatedRuntime.ts +572 -0
- package/src/runtime/schemaCompiler.ts +228 -0
- package/src/runtime/simpleRuntime.ts +201 -0
- package/src/security/dashboard.ts +462 -0
- package/src/security/hardening.ts +560 -0
- package/src/security/index.ts +439 -0
- package/src/security/monitor.ts +490 -0
- package/src/security/scanner.ts +368 -0
- package/src/security/score.ts +1138 -0
- package/src/security/threatDetector.ts +481 -0
- package/src/security/validation.ts +365 -0
- package/src/server/api/clientsRoute.ts +92 -0
- package/src/server/api/endpointsRoute.ts +97 -0
- package/src/server/api/graphql.ts +249 -0
- package/src/server/errors.ts +38 -0
- package/src/server/index.ts +6 -0
- package/src/server/kvStore.ts +152 -0
- package/src/server/runtimeSecurity.ts +102 -0
- package/src/server/types.ts +60 -0
- package/src/types/executionContext.ts +16 -0
- package/tools/seed.ts +365 -0
- package/tools/test-endpoints.ts +174 -0
|
@@ -0,0 +1,836 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarative Agent Runtime - YAML Interpreter for Beddel Declarative Protocol
|
|
3
|
+
* Safely interprets declarative YAML agent definitions without dynamic code execution
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as yaml from "js-yaml";
|
|
7
|
+
import { experimental_generateImage, generateText } from "ai";
|
|
8
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
9
|
+
import { type ZodTypeAny } from "zod";
|
|
10
|
+
import { ExecutionContext } from "../types/executionContext";
|
|
11
|
+
import {
|
|
12
|
+
DeclarativeSchemaCompiler,
|
|
13
|
+
DeclarativeSchemaValidationError,
|
|
14
|
+
type DeclarativeSchemaPhase,
|
|
15
|
+
} from "./schemaCompiler";
|
|
16
|
+
|
|
17
|
+
export interface YamlAgentDefinition {
|
|
18
|
+
agent: {
|
|
19
|
+
id: string;
|
|
20
|
+
version: string;
|
|
21
|
+
protocol: string;
|
|
22
|
+
};
|
|
23
|
+
metadata: {
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
category: string;
|
|
27
|
+
route?: string;
|
|
28
|
+
};
|
|
29
|
+
schema: {
|
|
30
|
+
input: any;
|
|
31
|
+
output: any;
|
|
32
|
+
};
|
|
33
|
+
logic: {
|
|
34
|
+
variables?: Array<{
|
|
35
|
+
name: string;
|
|
36
|
+
type: string;
|
|
37
|
+
init: string;
|
|
38
|
+
}>;
|
|
39
|
+
workflow: Array<{
|
|
40
|
+
name: string;
|
|
41
|
+
type: string;
|
|
42
|
+
action: {
|
|
43
|
+
type: string;
|
|
44
|
+
output?: Record<string, any>;
|
|
45
|
+
[key: string]: any;
|
|
46
|
+
};
|
|
47
|
+
}>;
|
|
48
|
+
};
|
|
49
|
+
output?: {
|
|
50
|
+
schema?: any;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface YamlAgentInterpreterOptions {
|
|
55
|
+
yamlContent: string;
|
|
56
|
+
input: Record<string, any>;
|
|
57
|
+
props: Record<string, string>;
|
|
58
|
+
context: ExecutionContext;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type YamlExecutionResult = Record<string, any>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Safe declarative YAML interpreter - no dynamic code execution
|
|
65
|
+
*/
|
|
66
|
+
export class DeclarativeAgentInterpreter {
|
|
67
|
+
private readonly MAX_VARIABLE_SIZE = 1024; // 1KB max variable size
|
|
68
|
+
private readonly MAX_WORKFLOW_STEPS = 100; // Prevent infinite loops
|
|
69
|
+
private readonly MAX_OUTPUT_SIZE = 5 * 1024 * 1024; // 5MB max output to accommodate image payloads
|
|
70
|
+
private readonly GEMINI_MODEL = "models/gemini-2.5-flash";
|
|
71
|
+
private readonly GEMINI_IMAGE_MODEL = "imagen-4.0-fast-generate-001";
|
|
72
|
+
private readonly SUPPORTED_TRANSLATION_LANGUAGES = ["pt", "en", "es", "fr"];
|
|
73
|
+
private readonly schemaCompiler = new DeclarativeSchemaCompiler();
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Interpret declarative YAML agent definition
|
|
77
|
+
*/
|
|
78
|
+
public async interpret(
|
|
79
|
+
options: YamlAgentInterpreterOptions
|
|
80
|
+
): Promise<YamlExecutionResult> {
|
|
81
|
+
const startTime = Date.now();
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
// Parse and validate YAML
|
|
85
|
+
const agent = this.parseYaml(options.yamlContent);
|
|
86
|
+
this.validateAgentDefinition(agent);
|
|
87
|
+
|
|
88
|
+
// Compile schemas and validate input up front
|
|
89
|
+
const schemas = this.buildSchemaSet(agent);
|
|
90
|
+
const validatedInput = this.validateAgainstSchema(
|
|
91
|
+
options.input,
|
|
92
|
+
schemas.input,
|
|
93
|
+
"input",
|
|
94
|
+
options.context
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const executionOptions: YamlAgentInterpreterOptions = {
|
|
98
|
+
...options,
|
|
99
|
+
input: validatedInput,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Execute declarative logic
|
|
103
|
+
const result = await this.executeWorkflow(agent, executionOptions);
|
|
104
|
+
|
|
105
|
+
// Validate output
|
|
106
|
+
const validatedOutput = this.validateAgainstSchema(
|
|
107
|
+
result,
|
|
108
|
+
schemas.output,
|
|
109
|
+
"output",
|
|
110
|
+
options.context
|
|
111
|
+
);
|
|
112
|
+
this.enforceOutputSize(validatedOutput);
|
|
113
|
+
|
|
114
|
+
const executionTime = Date.now() - startTime;
|
|
115
|
+
options.context.log(`Declarative agent executed in ${executionTime}ms`);
|
|
116
|
+
|
|
117
|
+
return validatedOutput;
|
|
118
|
+
} catch (error) {
|
|
119
|
+
const executionTime = Date.now() - startTime;
|
|
120
|
+
options.context.log(`Declarative agent execution failed: ${error}`);
|
|
121
|
+
options.context.setError(
|
|
122
|
+
error instanceof Error
|
|
123
|
+
? error.message
|
|
124
|
+
: "Unknown declarative agent error"
|
|
125
|
+
);
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Parse and validate YAML content
|
|
132
|
+
*/
|
|
133
|
+
private parseYaml(yamlContent: string): YamlAgentDefinition {
|
|
134
|
+
try {
|
|
135
|
+
const parsed = yaml.load(yamlContent) as YamlAgentDefinition;
|
|
136
|
+
|
|
137
|
+
if (!parsed || typeof parsed !== "object") {
|
|
138
|
+
throw new Error("Invalid YAML: expected object");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!parsed.agent || !parsed.logic || !parsed.schema) {
|
|
142
|
+
throw new Error("Invalid agent definition: missing required sections");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return parsed;
|
|
146
|
+
} catch (error) {
|
|
147
|
+
throw new Error(`YAML parsing failed: ${error}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Validate agent definition structure
|
|
153
|
+
*/
|
|
154
|
+
private validateAgentDefinition(agent: YamlAgentDefinition): void {
|
|
155
|
+
// Validate protocol version
|
|
156
|
+
if (agent.agent.protocol !== "beddel-declarative-protocol/v2.0") {
|
|
157
|
+
throw new Error(`Unsupported protocol: ${agent.agent.protocol}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Validate schema
|
|
161
|
+
if (!agent.schema.input || !agent.schema.output) {
|
|
162
|
+
throw new Error("Invalid schema: missing input or output definition");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Validate workflow
|
|
166
|
+
if (
|
|
167
|
+
!Array.isArray(agent.logic.workflow) ||
|
|
168
|
+
agent.logic.workflow.length === 0
|
|
169
|
+
) {
|
|
170
|
+
throw new Error("Invalid workflow: must be non-empty array");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (agent.logic.workflow.length > this.MAX_WORKFLOW_STEPS) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`Workflow too complex: max ${this.MAX_WORKFLOW_STEPS} steps allowed`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private buildSchemaSet(agent: YamlAgentDefinition): {
|
|
181
|
+
input: ZodTypeAny;
|
|
182
|
+
output: ZodTypeAny;
|
|
183
|
+
} {
|
|
184
|
+
return {
|
|
185
|
+
input: this.schemaCompiler.compile(agent.schema.input, "schema.input"),
|
|
186
|
+
output: this.schemaCompiler.compile(agent.schema.output, "schema.output"),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private validateAgainstSchema(
|
|
191
|
+
data: unknown,
|
|
192
|
+
schema: ZodTypeAny,
|
|
193
|
+
phase: DeclarativeSchemaPhase,
|
|
194
|
+
context: ExecutionContext
|
|
195
|
+
): any {
|
|
196
|
+
const validationResult = schema.safeParse(data);
|
|
197
|
+
if (!validationResult.success) {
|
|
198
|
+
const issues = validationResult.error.issues;
|
|
199
|
+
const issueSummary = issues
|
|
200
|
+
.map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`)
|
|
201
|
+
.join("; ");
|
|
202
|
+
const label = phase === "input" ? "Input" : "Output";
|
|
203
|
+
const message = `${label} validation failed: ${issueSummary}`;
|
|
204
|
+
context.setError(message);
|
|
205
|
+
throw new DeclarativeSchemaValidationError(message, phase, issues);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return validationResult.data;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private enforceOutputSize(output: any): void {
|
|
212
|
+
const outputSize = JSON.stringify(output).length;
|
|
213
|
+
if (outputSize > this.MAX_OUTPUT_SIZE) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`Output size exceeds maximum allowed: ${outputSize} > ${this.MAX_OUTPUT_SIZE}`
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Execute declarative workflow
|
|
222
|
+
*/
|
|
223
|
+
private async executeWorkflow(
|
|
224
|
+
agent: YamlAgentDefinition,
|
|
225
|
+
options: YamlAgentInterpreterOptions
|
|
226
|
+
): Promise<YamlExecutionResult> {
|
|
227
|
+
const variables = new Map<string, any>();
|
|
228
|
+
let output: any = undefined;
|
|
229
|
+
|
|
230
|
+
// Initialize variables
|
|
231
|
+
if (agent.logic.variables) {
|
|
232
|
+
for (const variable of agent.logic.variables) {
|
|
233
|
+
this.validateVariable(variable);
|
|
234
|
+
const value = this.evaluateValue(variable.init, variables);
|
|
235
|
+
variables.set(variable.name, value);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Execute workflow steps
|
|
240
|
+
for (const step of agent.logic.workflow) {
|
|
241
|
+
output = await this.executeWorkflowStep(step, variables, options);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return output;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Execute single workflow step
|
|
249
|
+
*/
|
|
250
|
+
private async executeWorkflowStep(
|
|
251
|
+
step: any,
|
|
252
|
+
variables: Map<string, any>,
|
|
253
|
+
options: YamlAgentInterpreterOptions
|
|
254
|
+
): Promise<any> {
|
|
255
|
+
options.context.log(`Executing workflow step: ${step.name} (${step.type})`);
|
|
256
|
+
|
|
257
|
+
switch (step.type) {
|
|
258
|
+
case "output-generator":
|
|
259
|
+
return this.executeOutputGenerator(step, variables, options);
|
|
260
|
+
case "genkit-joke":
|
|
261
|
+
return this.executeGenkitJoke(step, variables, options);
|
|
262
|
+
case "genkit-translation":
|
|
263
|
+
return this.executeGenkitTranslation(step, variables, options);
|
|
264
|
+
case "genkit-image":
|
|
265
|
+
return this.executeGenkitImage(step, variables, options);
|
|
266
|
+
default:
|
|
267
|
+
throw new Error(`Unsupported workflow step type: ${step.type}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Execute output generator step
|
|
273
|
+
*/
|
|
274
|
+
private executeOutputGenerator(
|
|
275
|
+
step: any,
|
|
276
|
+
variables: Map<string, any>,
|
|
277
|
+
options: YamlAgentInterpreterOptions
|
|
278
|
+
): any {
|
|
279
|
+
if (step.action?.type !== "generate" || !step.action.output) {
|
|
280
|
+
throw new Error("Invalid output generator configuration");
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Build output object
|
|
284
|
+
const output: any = {};
|
|
285
|
+
|
|
286
|
+
// Debug: Log available variables
|
|
287
|
+
options.context.log(
|
|
288
|
+
`Output generator: Available variables: ${Array.from(variables.keys()).join(", ")}`
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
for (const [key, valueExpr] of Object.entries(step.action.output)) {
|
|
292
|
+
if (typeof valueExpr === "string" && valueExpr.startsWith("$")) {
|
|
293
|
+
try {
|
|
294
|
+
const reference = valueExpr.substring(1);
|
|
295
|
+
options.context.log(
|
|
296
|
+
`Output generator: Resolving reference ${valueExpr} -> ${reference}`
|
|
297
|
+
);
|
|
298
|
+
const resolved = this.resolveReference(reference, variables);
|
|
299
|
+
output[key] = resolved;
|
|
300
|
+
options.context.log(
|
|
301
|
+
`Output generator: Resolved ${key} = ${typeof resolved === "string" ? resolved.substring(0, 50) + "..." : JSON.stringify(resolved).substring(0, 100)}`
|
|
302
|
+
);
|
|
303
|
+
} catch (error) {
|
|
304
|
+
options.context.log(
|
|
305
|
+
`Output generator: Failed to resolve ${valueExpr}: ${error instanceof Error ? error.message : String(error)}`
|
|
306
|
+
);
|
|
307
|
+
throw error;
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
output[key] = valueExpr;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
options.context.log(
|
|
315
|
+
`Output generator: Final output keys: ${Object.keys(output).join(", ")}`
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
return output;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Execute Gemini Flash text helper for the joke agent
|
|
323
|
+
*/
|
|
324
|
+
private async executeGenkitJoke(
|
|
325
|
+
step: any,
|
|
326
|
+
variables: Map<string, any>,
|
|
327
|
+
options: YamlAgentInterpreterOptions
|
|
328
|
+
): Promise<any> {
|
|
329
|
+
const prompt =
|
|
330
|
+
typeof step.action?.prompt === "string" && step.action.prompt.trim().length
|
|
331
|
+
? step.action.prompt.trim()
|
|
332
|
+
: "Conte uma piada curta e original em português.";
|
|
333
|
+
const temperature =
|
|
334
|
+
typeof step.action?.temperature === "number"
|
|
335
|
+
? step.action.temperature
|
|
336
|
+
: 0.8;
|
|
337
|
+
const maxTokens =
|
|
338
|
+
typeof step.action?.maxTokens === "number"
|
|
339
|
+
? step.action.maxTokens
|
|
340
|
+
: undefined;
|
|
341
|
+
const resultVar =
|
|
342
|
+
typeof step.action?.result === "string" && step.action.result.length > 0
|
|
343
|
+
? step.action.result
|
|
344
|
+
: "jokerResult";
|
|
345
|
+
|
|
346
|
+
const joke = await this.callGeminiFlashText(
|
|
347
|
+
{ prompt, temperature, maxTokens },
|
|
348
|
+
options.props,
|
|
349
|
+
options.context
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
variables.set(resultVar, joke);
|
|
353
|
+
return joke;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Execute translation step backed by Gemini Flash
|
|
358
|
+
*/
|
|
359
|
+
private async executeGenkitTranslation(
|
|
360
|
+
step: any,
|
|
361
|
+
variables: Map<string, any>,
|
|
362
|
+
options: YamlAgentInterpreterOptions
|
|
363
|
+
): Promise<any> {
|
|
364
|
+
const texto = options.input?.texto;
|
|
365
|
+
const idiomaOrigem = options.input?.idioma_origem;
|
|
366
|
+
const idiomaDestino = options.input?.idioma_destino;
|
|
367
|
+
|
|
368
|
+
const resultVar =
|
|
369
|
+
typeof step.action?.result === "string" && step.action.result.length > 0
|
|
370
|
+
? step.action.result
|
|
371
|
+
: "translationResult";
|
|
372
|
+
|
|
373
|
+
const translation = await this.callGeminiFlashTranslation(
|
|
374
|
+
{
|
|
375
|
+
texto,
|
|
376
|
+
idioma_origem: idiomaOrigem,
|
|
377
|
+
idioma_destino: idiomaDestino,
|
|
378
|
+
promptTemplate:
|
|
379
|
+
typeof step.action?.promptTemplate === "string"
|
|
380
|
+
? step.action.promptTemplate
|
|
381
|
+
: undefined,
|
|
382
|
+
},
|
|
383
|
+
options.props,
|
|
384
|
+
options.context
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
variables.set(resultVar, translation);
|
|
388
|
+
return translation;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Execute image generation step backed by Gemini Flash
|
|
393
|
+
*/
|
|
394
|
+
private async executeGenkitImage(
|
|
395
|
+
step: any,
|
|
396
|
+
variables: Map<string, any>,
|
|
397
|
+
options: YamlAgentInterpreterOptions
|
|
398
|
+
): Promise<any> {
|
|
399
|
+
const descricao =
|
|
400
|
+
typeof options.input?.descricao === "string"
|
|
401
|
+
? options.input.descricao.trim()
|
|
402
|
+
: "";
|
|
403
|
+
const estilo =
|
|
404
|
+
typeof options.input?.estilo === "string"
|
|
405
|
+
? options.input.estilo.trim()
|
|
406
|
+
: "";
|
|
407
|
+
const resolucaoInput =
|
|
408
|
+
typeof options.input?.resolucao === "string"
|
|
409
|
+
? options.input.resolucao.trim()
|
|
410
|
+
: "";
|
|
411
|
+
|
|
412
|
+
if (!descricao) {
|
|
413
|
+
throw new Error("Missing required image input: descricao");
|
|
414
|
+
}
|
|
415
|
+
if (!estilo) {
|
|
416
|
+
throw new Error("Missing required image input: estilo");
|
|
417
|
+
}
|
|
418
|
+
if (!resolucaoInput) {
|
|
419
|
+
throw new Error("Missing required image input: resolucao");
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const promptTemplate =
|
|
423
|
+
typeof step.action?.promptTemplate === "string" &&
|
|
424
|
+
step.action.promptTemplate.trim().length > 0
|
|
425
|
+
? step.action.promptTemplate
|
|
426
|
+
: "Gere uma imagem detalhada no estilo {{estilo}} baseada na descrição: {{descricao}}";
|
|
427
|
+
|
|
428
|
+
const prompt = promptTemplate
|
|
429
|
+
.replace(/{{descricao}}/g, descricao)
|
|
430
|
+
.replace(/{{estilo}}/g, estilo)
|
|
431
|
+
.trim();
|
|
432
|
+
|
|
433
|
+
const resultVar =
|
|
434
|
+
typeof step.action?.result === "string" && step.action.result.length > 0
|
|
435
|
+
? step.action.result
|
|
436
|
+
: "imageResult";
|
|
437
|
+
|
|
438
|
+
const imageResult = await this.callGeminiFlashImage(
|
|
439
|
+
{
|
|
440
|
+
prompt,
|
|
441
|
+
estilo,
|
|
442
|
+
resolucao: resolucaoInput,
|
|
443
|
+
},
|
|
444
|
+
options.props,
|
|
445
|
+
options.context
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
variables.set(resultVar, imageResult);
|
|
449
|
+
options.context.log(
|
|
450
|
+
`Image generator: Saved result in variable '${resultVar}' with keys: ${Object.keys(imageResult).join(", ")}`
|
|
451
|
+
);
|
|
452
|
+
options.context.log(
|
|
453
|
+
`Image generator: imageResult.image_url exists: ${!!imageResult?.image_url}`
|
|
454
|
+
);
|
|
455
|
+
return imageResult;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Evaluate value expression
|
|
460
|
+
*/
|
|
461
|
+
private evaluateValue(expr: string, variables: Map<string, any>): any {
|
|
462
|
+
// Handle string literals
|
|
463
|
+
if (expr.startsWith('"') && expr.endsWith('"')) {
|
|
464
|
+
if (expr.length - 2 > this.MAX_VARIABLE_SIZE) {
|
|
465
|
+
throw new Error("Variable initialization exceeds maximum size");
|
|
466
|
+
}
|
|
467
|
+
return expr.slice(1, -1);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (expr.startsWith("'") && expr.endsWith("'")) {
|
|
471
|
+
if (expr.length - 2 > this.MAX_VARIABLE_SIZE) {
|
|
472
|
+
throw new Error("Variable initialization exceeds maximum size");
|
|
473
|
+
}
|
|
474
|
+
return expr.slice(1, -1);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (expr.length > this.MAX_VARIABLE_SIZE) {
|
|
478
|
+
throw new Error("Variable initialization exceeds maximum size");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Handle boolean literals
|
|
482
|
+
if (expr === "true") return true;
|
|
483
|
+
if (expr === "false") return false;
|
|
484
|
+
|
|
485
|
+
// Handle null literal
|
|
486
|
+
if (expr === "null") return null;
|
|
487
|
+
|
|
488
|
+
// Handle variable references
|
|
489
|
+
if (expr.startsWith("$")) {
|
|
490
|
+
return this.resolveReference(expr.substring(1), variables);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Handle numbers
|
|
494
|
+
if (/^-?\d+$/.test(expr)) return parseInt(expr, 10);
|
|
495
|
+
if (/^-?\d+\.\d+$/.test(expr)) return parseFloat(expr);
|
|
496
|
+
|
|
497
|
+
throw new Error(`Unsupported value expression: ${expr}`);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Validate variable declaration
|
|
502
|
+
*/
|
|
503
|
+
private validateVariable(variable: any): void {
|
|
504
|
+
if (!variable.name || !variable.type) {
|
|
505
|
+
throw new Error("Invalid variable declaration: missing name or type");
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (!["string", "number", "boolean", "object"].includes(variable.type)) {
|
|
509
|
+
throw new Error(`Unsupported variable type: ${variable.type}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Resolve variable reference, including nested properties (e.g., foo.bar.baz)
|
|
515
|
+
*/
|
|
516
|
+
private resolveReference(
|
|
517
|
+
reference: string,
|
|
518
|
+
variables: Map<string, any>
|
|
519
|
+
): any {
|
|
520
|
+
const [varName, ...pathSegments] = reference.split(".");
|
|
521
|
+
let value = variables.get(varName);
|
|
522
|
+
if (value === undefined) {
|
|
523
|
+
throw new Error(`Undefined variable referenced: ${varName}`);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
for (const segment of pathSegments) {
|
|
527
|
+
if (value == null || typeof value !== "object") {
|
|
528
|
+
throw new Error(
|
|
529
|
+
`Cannot resolve path '${reference}': segment '${segment}' is invalid`
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
value = value[segment];
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return value;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Ensure we have a Gemini API key before calling Genkit helpers
|
|
540
|
+
*/
|
|
541
|
+
private ensureGeminiApiKey(props: Record<string, string>): string {
|
|
542
|
+
const apiKey = props?.gemini_api_key?.trim();
|
|
543
|
+
if (!apiKey) {
|
|
544
|
+
throw new Error(
|
|
545
|
+
"Missing required prop: gemini_api_key. Configure a valid Gemini API key before calling this agent."
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
return apiKey;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
private createGeminiModel(props: Record<string, string>) {
|
|
552
|
+
const apiKey = this.ensureGeminiApiKey(props);
|
|
553
|
+
const google = createGoogleGenerativeAI({ apiKey });
|
|
554
|
+
const model = google(this.GEMINI_MODEL);
|
|
555
|
+
return model;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
private createGeminiImageModel(props: Record<string, string>) {
|
|
559
|
+
const apiKey = this.ensureGeminiApiKey(props);
|
|
560
|
+
const google = createGoogleGenerativeAI({ apiKey });
|
|
561
|
+
return google.image(this.GEMINI_IMAGE_MODEL);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
private async callGeminiFlashText(
|
|
565
|
+
params: {
|
|
566
|
+
prompt: string;
|
|
567
|
+
temperature?: number;
|
|
568
|
+
maxTokens?: number;
|
|
569
|
+
},
|
|
570
|
+
props: Record<string, string>,
|
|
571
|
+
context: ExecutionContext
|
|
572
|
+
): Promise<{
|
|
573
|
+
texto: string;
|
|
574
|
+
metadados: {
|
|
575
|
+
modelo_utilizado: string;
|
|
576
|
+
tempo_processamento: number;
|
|
577
|
+
temperature: number;
|
|
578
|
+
max_tokens: number | null;
|
|
579
|
+
prompt_utilizado: string;
|
|
580
|
+
};
|
|
581
|
+
}> {
|
|
582
|
+
const prompt = params.prompt?.trim();
|
|
583
|
+
if (!prompt) {
|
|
584
|
+
throw new Error("Gemini Flash text helper requires a prompt");
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const temperature =
|
|
588
|
+
typeof params.temperature === "number" ? params.temperature : 0.7;
|
|
589
|
+
const maxTokens =
|
|
590
|
+
typeof params.maxTokens === "number" ? params.maxTokens : undefined;
|
|
591
|
+
|
|
592
|
+
const model = this.createGeminiModel(props);
|
|
593
|
+
const startTime = Date.now();
|
|
594
|
+
|
|
595
|
+
try {
|
|
596
|
+
context.log(
|
|
597
|
+
`Invoking Gemini Flash text helper (temperature=${temperature}, maxTokens=${
|
|
598
|
+
typeof maxTokens === "number" ? maxTokens : "provider-default"
|
|
599
|
+
})`
|
|
600
|
+
);
|
|
601
|
+
const generationOptions: Record<string, any> = {
|
|
602
|
+
model,
|
|
603
|
+
prompt,
|
|
604
|
+
temperature,
|
|
605
|
+
};
|
|
606
|
+
if (typeof maxTokens === "number") {
|
|
607
|
+
generationOptions.maxOutputTokens = maxTokens;
|
|
608
|
+
}
|
|
609
|
+
const { text, content } = await generateText(
|
|
610
|
+
generationOptions as any
|
|
611
|
+
);
|
|
612
|
+
const contentText = content
|
|
613
|
+
? content
|
|
614
|
+
.map((part: any) =>
|
|
615
|
+
typeof part?.text === "string" ? part.text : ""
|
|
616
|
+
)
|
|
617
|
+
.join(" ")
|
|
618
|
+
.trim()
|
|
619
|
+
: "";
|
|
620
|
+
const finalText = (text || "").trim() || contentText || "";
|
|
621
|
+
if (!finalText) {
|
|
622
|
+
throw new Error("Gemini Flash text helper returned empty response");
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return {
|
|
626
|
+
texto: finalText,
|
|
627
|
+
metadados: {
|
|
628
|
+
modelo_utilizado: this.GEMINI_MODEL,
|
|
629
|
+
tempo_processamento: Date.now() - startTime,
|
|
630
|
+
temperature,
|
|
631
|
+
max_tokens: typeof maxTokens === "number" ? maxTokens : null,
|
|
632
|
+
prompt_utilizado: prompt,
|
|
633
|
+
},
|
|
634
|
+
};
|
|
635
|
+
} catch (error) {
|
|
636
|
+
const message =
|
|
637
|
+
error instanceof Error ? error.message : "Unknown Gemini Flash error";
|
|
638
|
+
context.log(`Gemini Flash text helper failed: ${message}`);
|
|
639
|
+
context.setError(message);
|
|
640
|
+
throw error;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
private async callGeminiFlashTranslation(
|
|
645
|
+
params: {
|
|
646
|
+
texto?: string;
|
|
647
|
+
idioma_origem?: string;
|
|
648
|
+
idioma_destino?: string;
|
|
649
|
+
promptTemplate?: string;
|
|
650
|
+
},
|
|
651
|
+
props: Record<string, string>,
|
|
652
|
+
context: ExecutionContext
|
|
653
|
+
): Promise<{
|
|
654
|
+
texto_traduzido: string;
|
|
655
|
+
metadados: {
|
|
656
|
+
modelo_utilizado: string;
|
|
657
|
+
tempo_processamento: number;
|
|
658
|
+
confianca: number;
|
|
659
|
+
idiomas_suportados: string[];
|
|
660
|
+
idiomas_solicitados: {
|
|
661
|
+
origem: string;
|
|
662
|
+
destino: string;
|
|
663
|
+
};
|
|
664
|
+
prompt_utilizado: string;
|
|
665
|
+
};
|
|
666
|
+
}> {
|
|
667
|
+
const texto = params.texto?.trim();
|
|
668
|
+
const idiomaOrigem = params.idioma_origem?.trim().toLowerCase();
|
|
669
|
+
const idiomaDestino = params.idioma_destino?.trim().toLowerCase();
|
|
670
|
+
|
|
671
|
+
if (!texto || !idiomaOrigem || !idiomaDestino) {
|
|
672
|
+
throw new Error(
|
|
673
|
+
"Missing required translation parameters: texto, idioma_origem, idioma_destino"
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if (idiomaOrigem === idiomaDestino) {
|
|
678
|
+
return {
|
|
679
|
+
texto_traduzido: texto,
|
|
680
|
+
metadados: {
|
|
681
|
+
modelo_utilizado: this.GEMINI_MODEL,
|
|
682
|
+
tempo_processamento: 0,
|
|
683
|
+
confianca: 1,
|
|
684
|
+
idiomas_suportados: this.SUPPORTED_TRANSLATION_LANGUAGES,
|
|
685
|
+
idiomas_solicitados: {
|
|
686
|
+
origem: idiomaOrigem,
|
|
687
|
+
destino: idiomaDestino,
|
|
688
|
+
},
|
|
689
|
+
prompt_utilizado: "Bypass: idiomas de origem e destino são iguais",
|
|
690
|
+
},
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const template =
|
|
695
|
+
params.promptTemplate && params.promptTemplate.trim().length > 0
|
|
696
|
+
? params.promptTemplate
|
|
697
|
+
: `Traduza o texto abaixo de {{idioma_origem}} para {{idioma_destino}}.
|
|
698
|
+
Responda somente com o texto traduzido sem comentários adicionais.
|
|
699
|
+
|
|
700
|
+
Texto:
|
|
701
|
+
{{texto}}`;
|
|
702
|
+
|
|
703
|
+
const prompt = template
|
|
704
|
+
.replace(/{{texto}}/g, texto)
|
|
705
|
+
.replace(/{{idioma_origem}}/g, idiomaOrigem)
|
|
706
|
+
.replace(/{{idioma_destino}}/g, idiomaDestino)
|
|
707
|
+
.trim();
|
|
708
|
+
|
|
709
|
+
const model = this.createGeminiModel(props);
|
|
710
|
+
const startTime = Date.now();
|
|
711
|
+
|
|
712
|
+
try {
|
|
713
|
+
context.log(
|
|
714
|
+
`Invoking Gemini Flash translation helper (${idiomaOrigem}->${idiomaDestino})`
|
|
715
|
+
);
|
|
716
|
+
const { text, content } = await generateText({
|
|
717
|
+
model,
|
|
718
|
+
prompt,
|
|
719
|
+
temperature: 0.2,
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
const contentText = content
|
|
723
|
+
? content
|
|
724
|
+
.map((part: any) =>
|
|
725
|
+
typeof part?.text === "string" ? part.text : ""
|
|
726
|
+
)
|
|
727
|
+
.join(" ")
|
|
728
|
+
.trim()
|
|
729
|
+
: "";
|
|
730
|
+
const translatedText = (text || "").trim() || contentText || "";
|
|
731
|
+
if (!translatedText) {
|
|
732
|
+
throw new Error("Gemini Flash translation returned empty response");
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
return {
|
|
736
|
+
texto_traduzido: translatedText,
|
|
737
|
+
metadados: {
|
|
738
|
+
modelo_utilizado: this.GEMINI_MODEL,
|
|
739
|
+
tempo_processamento: Date.now() - startTime,
|
|
740
|
+
confianca: 0.85,
|
|
741
|
+
idiomas_suportados: this.SUPPORTED_TRANSLATION_LANGUAGES,
|
|
742
|
+
idiomas_solicitados: {
|
|
743
|
+
origem: idiomaOrigem,
|
|
744
|
+
destino: idiomaDestino,
|
|
745
|
+
},
|
|
746
|
+
prompt_utilizado: prompt,
|
|
747
|
+
},
|
|
748
|
+
};
|
|
749
|
+
} catch (error) {
|
|
750
|
+
const message =
|
|
751
|
+
error instanceof Error ? error.message : "Unknown translation error";
|
|
752
|
+
context.log(`Gemini Flash translation failed: ${message}`);
|
|
753
|
+
context.setError(message);
|
|
754
|
+
throw error;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
private async callGeminiFlashImage(
|
|
759
|
+
params: { prompt: string; estilo: string; resolucao: string },
|
|
760
|
+
props: Record<string, string>,
|
|
761
|
+
context: ExecutionContext
|
|
762
|
+
): Promise<{
|
|
763
|
+
image_url: string;
|
|
764
|
+
image_base64: string;
|
|
765
|
+
media_type: string;
|
|
766
|
+
prompt_utilizado: string;
|
|
767
|
+
metadados: {
|
|
768
|
+
modelo_utilizado: string;
|
|
769
|
+
tempo_processamento: number;
|
|
770
|
+
estilo: string;
|
|
771
|
+
resolucao: string;
|
|
772
|
+
};
|
|
773
|
+
}> {
|
|
774
|
+
const prompt = params.prompt?.trim();
|
|
775
|
+
const estilo = params.estilo?.trim();
|
|
776
|
+
const resolucao = params.resolucao?.trim();
|
|
777
|
+
|
|
778
|
+
if (!prompt) {
|
|
779
|
+
throw new Error("Gemini Flash image helper requires a prompt");
|
|
780
|
+
}
|
|
781
|
+
if (!estilo) {
|
|
782
|
+
throw new Error("Gemini Flash image helper requires an estilo value");
|
|
783
|
+
}
|
|
784
|
+
if (!resolucao || !/^\d+x\d+$/.test(resolucao)) {
|
|
785
|
+
throw new Error(
|
|
786
|
+
"Gemini Flash image helper requires uma resolução no formato LARGURAxALTURA (ex: 1024x1024)"
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
const model = this.createGeminiImageModel(props);
|
|
791
|
+
const startTime = Date.now();
|
|
792
|
+
|
|
793
|
+
try {
|
|
794
|
+
context.log(
|
|
795
|
+
`Invoking Gemini Flash image helper (estilo=${estilo}, resolucao=${resolucao})`
|
|
796
|
+
);
|
|
797
|
+
const result = await experimental_generateImage({
|
|
798
|
+
model,
|
|
799
|
+
prompt,
|
|
800
|
+
size: resolucao as `${number}x${number}`,
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
const image = result.image;
|
|
804
|
+
if (!image?.base64 || !image.mediaType) {
|
|
805
|
+
throw new Error("Gemini Flash image helper returned an invalid file");
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
const normalizedBase64 = image.base64.replace(/\s+/g, "");
|
|
809
|
+
const imageUrl = `data:${image.mediaType};base64,${normalizedBase64}`;
|
|
810
|
+
|
|
811
|
+
return {
|
|
812
|
+
image_url: imageUrl,
|
|
813
|
+
image_base64: normalizedBase64,
|
|
814
|
+
media_type: image.mediaType,
|
|
815
|
+
prompt_utilizado: prompt,
|
|
816
|
+
metadados: {
|
|
817
|
+
modelo_utilizado: this.GEMINI_IMAGE_MODEL,
|
|
818
|
+
tempo_processamento: Date.now() - startTime,
|
|
819
|
+
estilo,
|
|
820
|
+
resolucao,
|
|
821
|
+
},
|
|
822
|
+
};
|
|
823
|
+
} catch (error) {
|
|
824
|
+
const message =
|
|
825
|
+
error instanceof Error ? error.message : "Unknown image error";
|
|
826
|
+
context.log(`Gemini Flash image helper failed: ${message}`);
|
|
827
|
+
context.setError(message);
|
|
828
|
+
throw error;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// Singleton instance
|
|
834
|
+
export const declarativeInterpreter = new DeclarativeAgentInterpreter();
|
|
835
|
+
|
|
836
|
+
export default DeclarativeAgentInterpreter;
|