@nebulaos/core 0.1.1
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 +206 -0
- package/dist/__tests__/mocks/mock-provider.d.ts +15 -0
- package/dist/__tests__/mocks/mock-provider.js +44 -0
- package/dist/agent/Agent.d.ts +96 -0
- package/dist/agent/Agent.js +861 -0
- package/dist/agent/BaseAgent.d.ts +53 -0
- package/dist/agent/BaseAgent.js +126 -0
- package/dist/agent/events/events.d.ts +14 -0
- package/dist/agent/events/events.js +2 -0
- package/dist/agent/events/events.spec.d.ts +1 -0
- package/dist/agent/events/events.spec.js +75 -0
- package/dist/agent/instruction/index.d.ts +23 -0
- package/dist/agent/instruction/index.js +76 -0
- package/dist/agent/memory/in-memory.d.ts +24 -0
- package/dist/agent/memory/in-memory.js +78 -0
- package/dist/agent/memory/index.d.ts +2 -0
- package/dist/agent/memory/index.js +18 -0
- package/dist/agent/memory/memory.d.ts +43 -0
- package/dist/agent/memory/memory.js +7 -0
- package/dist/agent/provider/file-parts.spec.d.ts +1 -0
- package/dist/agent/provider/file-parts.spec.js +83 -0
- package/dist/agent/provider/index.d.ts +130 -0
- package/dist/agent/provider/index.js +8 -0
- package/dist/agent/skills/index.d.ts +61 -0
- package/dist/agent/skills/index.js +9 -0
- package/dist/agent/tools/index.d.ts +35 -0
- package/dist/agent/tools/index.js +87 -0
- package/dist/cost/add-cost.d.ts +10 -0
- package/dist/cost/add-cost.js +80 -0
- package/dist/cost/add-cost.spec.d.ts +1 -0
- package/dist/cost/add-cost.spec.js +36 -0
- package/dist/cost/index.d.ts +1 -0
- package/dist/cost/index.js +17 -0
- package/dist/domain-events/index.d.ts +16 -0
- package/dist/domain-events/index.js +38 -0
- package/dist/eval/index.d.ts +19 -0
- package/dist/eval/index.js +24 -0
- package/dist/events/base.d.ts +5 -0
- package/dist/events/base.js +2 -0
- package/dist/events/schemas.d.ts +3463 -0
- package/dist/events/schemas.js +244 -0
- package/dist/execution-context/index.d.ts +21 -0
- package/dist/execution-context/index.js +17 -0
- package/dist/index.cjs +2958 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3425 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/lgpd/index.d.ts +7 -0
- package/dist/lgpd/index.js +21 -0
- package/dist/logger/agent-logger.d.ts +16 -0
- package/dist/logger/agent-logger.js +110 -0
- package/dist/logger/formatters.d.ts +32 -0
- package/dist/logger/formatters.js +146 -0
- package/dist/logger/index.d.ts +30 -0
- package/dist/logger/index.js +88 -0
- package/dist/logger/styles.d.ts +46 -0
- package/dist/logger/styles.js +53 -0
- package/dist/logger/workflow-logger.d.ts +16 -0
- package/dist/logger/workflow-logger.js +79 -0
- package/dist/multi-agent/agent-as-tool/AgentAsTool.d.ts +16 -0
- package/dist/multi-agent/agent-as-tool/AgentAsTool.js +54 -0
- package/dist/multi-agent/agent-as-tool/AgentAsTool.spec.d.ts +1 -0
- package/dist/multi-agent/agent-as-tool/AgentAsTool.spec.js +76 -0
- package/dist/multi-agent/committee-team/CommitteeTeam.d.ts +16 -0
- package/dist/multi-agent/committee-team/CommitteeTeam.js +150 -0
- package/dist/multi-agent/committee-team/CommitteeTeam.spec.d.ts +1 -0
- package/dist/multi-agent/committee-team/CommitteeTeam.spec.js +43 -0
- package/dist/multi-agent/handoff-team/HandoffTeam.d.ts +16 -0
- package/dist/multi-agent/handoff-team/HandoffTeam.js +185 -0
- package/dist/multi-agent/handoff-team/HandoffTeam.spec.d.ts +1 -0
- package/dist/multi-agent/handoff-team/HandoffTeam.spec.js +105 -0
- package/dist/multi-agent/hierarchical-team/HierarchicalTeam.d.ts +18 -0
- package/dist/multi-agent/hierarchical-team/HierarchicalTeam.js +164 -0
- package/dist/multi-agent/hierarchical-team/HierarchicalTeam.spec.d.ts +1 -0
- package/dist/multi-agent/hierarchical-team/HierarchicalTeam.spec.js +53 -0
- package/dist/multi-agent/index.d.ts +10 -0
- package/dist/multi-agent/index.js +26 -0
- package/dist/multi-agent/pipeline-team/PipelineTeam.d.ts +13 -0
- package/dist/multi-agent/pipeline-team/PipelineTeam.js +104 -0
- package/dist/multi-agent/pipeline-team/PipelineTeam.spec.d.ts +1 -0
- package/dist/multi-agent/pipeline-team/PipelineTeam.spec.js +54 -0
- package/dist/multi-agent/router-team/RouterTeam.d.ts +15 -0
- package/dist/multi-agent/router-team/RouterTeam.js +153 -0
- package/dist/multi-agent/router-team/RouterTeam.spec.d.ts +1 -0
- package/dist/multi-agent/router-team/RouterTeam.spec.js +69 -0
- package/dist/multi-agent/types/index.d.ts +349 -0
- package/dist/multi-agent/types/index.js +79 -0
- package/dist/multi-agent/utils/guardrails.d.ts +6 -0
- package/dist/multi-agent/utils/guardrails.js +34 -0
- package/dist/multi-agent/utils/memory.d.ts +8 -0
- package/dist/multi-agent/utils/memory.js +40 -0
- package/dist/multi-agent/utils/prompts.d.ts +4 -0
- package/dist/multi-agent/utils/prompts.js +25 -0
- package/dist/tracing/index.d.ts +89 -0
- package/dist/tracing/index.js +188 -0
- package/dist/tsup.config.d.ts +2 -0
- package/dist/tsup.config.js +11 -0
- package/dist/utils/schema-to-zod.d.ts +7 -0
- package/dist/utils/schema-to-zod.js +36 -0
- package/dist/workflow/Workflow.d.ts +106 -0
- package/dist/workflow/Workflow.js +204 -0
- package/dist/workflow/adapters.d.ts +61 -0
- package/dist/workflow/adapters.js +29 -0
- package/dist/workflow/definition/DefinitionBuilder.d.ts +9 -0
- package/dist/workflow/definition/DefinitionBuilder.js +91 -0
- package/dist/workflow/definition/DefinitionBuilder.spec.d.ts +1 -0
- package/dist/workflow/definition/DefinitionBuilder.spec.js +66 -0
- package/dist/workflow/definition/DefinitionHasher.d.ts +8 -0
- package/dist/workflow/definition/DefinitionHasher.js +11 -0
- package/dist/workflow/definition/DefinitionHasher.spec.d.ts +1 -0
- package/dist/workflow/definition/DefinitionHasher.spec.js +28 -0
- package/dist/workflow/definition/types.d.ts +27 -0
- package/dist/workflow/definition/types.js +2 -0
- package/dist/workflow/events.d.ts +9 -0
- package/dist/workflow/events.js +2 -0
- package/dist/workflow/execution/AgentNodeIntegration.spec.d.ts +1 -0
- package/dist/workflow/execution/AgentNodeIntegration.spec.js +50 -0
- package/dist/workflow/execution/NodeExecutor.d.ts +9 -0
- package/dist/workflow/execution/NodeExecutor.js +43 -0
- package/dist/workflow/execution/NodeExecutor.spec.d.ts +1 -0
- package/dist/workflow/execution/NodeExecutor.spec.js +45 -0
- package/dist/workflow/execution/WorkflowEventBus.d.ts +14 -0
- package/dist/workflow/execution/WorkflowEventBus.js +42 -0
- package/dist/workflow/execution/WorkflowEventBus.spec.d.ts +1 -0
- package/dist/workflow/execution/WorkflowEventBus.spec.js +78 -0
- package/dist/workflow/execution/WorkflowRunner.d.ts +26 -0
- package/dist/workflow/execution/WorkflowRunner.js +212 -0
- package/dist/workflow/execution/WorkflowRunner.spec.d.ts +1 -0
- package/dist/workflow/execution/WorkflowRunner.spec.js +92 -0
- package/dist/workflow/execution/WorkflowTelemetry.d.ts +13 -0
- package/dist/workflow/execution/WorkflowTelemetry.js +43 -0
- package/dist/workflow/execution/WorkflowTelemetry.spec.d.ts +1 -0
- package/dist/workflow/execution/WorkflowTelemetry.spec.js +31 -0
- package/dist/workflow/graph/NodeNameRegistry.d.ts +20 -0
- package/dist/workflow/graph/NodeNameRegistry.js +21 -0
- package/dist/workflow/graph/NodeNameRegistry.spec.d.ts +1 -0
- package/dist/workflow/graph/NodeNameRegistry.spec.js +18 -0
- package/dist/workflow/graph/WorkflowGraph.d.ts +14 -0
- package/dist/workflow/graph/WorkflowGraph.js +23 -0
- package/dist/workflow/graph/nodes.d.ts +26 -0
- package/dist/workflow/graph/nodes.js +2 -0
- package/dist/workflow/queue/WorkflowQueueService.d.ts +22 -0
- package/dist/workflow/queue/WorkflowQueueService.js +47 -0
- package/dist/workflow/state/WorkflowStateService.d.ts +7 -0
- package/dist/workflow/state/WorkflowStateService.js +20 -0
- package/dist/workflow/types.d.ts +16 -0
- package/dist/workflow/types.js +2 -0
- package/package.json +56 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Provider Interfaces
|
|
3
|
+
*
|
|
4
|
+
* Define o contrato que qualquer provedor de LLM (OpenAI, Anthropic, etc.)
|
|
5
|
+
* deve implementar para ser compatível com o Agent.
|
|
6
|
+
*/
|
|
7
|
+
export type Role = "system" | "user" | "assistant" | "function" | "tool";
|
|
8
|
+
export type ToolCall = {
|
|
9
|
+
id: string;
|
|
10
|
+
type: "function";
|
|
11
|
+
function: {
|
|
12
|
+
name: string;
|
|
13
|
+
arguments: string;
|
|
14
|
+
};
|
|
15
|
+
/** Gemini thought signature - must be preserved for Gemini 3+ models */
|
|
16
|
+
thought_signature?: string;
|
|
17
|
+
};
|
|
18
|
+
export type FileSource = {
|
|
19
|
+
type: "url";
|
|
20
|
+
url: string;
|
|
21
|
+
sizeBytes?: number;
|
|
22
|
+
} | {
|
|
23
|
+
type: "base64";
|
|
24
|
+
base64: string;
|
|
25
|
+
};
|
|
26
|
+
export type ContentPart = {
|
|
27
|
+
type: "text";
|
|
28
|
+
text: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: "file";
|
|
31
|
+
file: {
|
|
32
|
+
/** Optional display name (e.g., "invoice.pdf") */
|
|
33
|
+
name?: string;
|
|
34
|
+
/** MIME type (e.g., "application/pdf", "image/png") */
|
|
35
|
+
mimeType: string;
|
|
36
|
+
source: FileSource;
|
|
37
|
+
};
|
|
38
|
+
} | {
|
|
39
|
+
/** Direct image URL format (compatible with OpenAI API) */
|
|
40
|
+
type: "image_url";
|
|
41
|
+
image_url: {
|
|
42
|
+
url: string;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export type Message = {
|
|
46
|
+
role: Role;
|
|
47
|
+
content?: string | ContentPart[] | null;
|
|
48
|
+
name?: string;
|
|
49
|
+
tool_calls?: ToolCall[];
|
|
50
|
+
tool_call_id?: string;
|
|
51
|
+
};
|
|
52
|
+
export type TokenUsage = {
|
|
53
|
+
promptTokens: number;
|
|
54
|
+
completionTokens: number;
|
|
55
|
+
totalTokens: number;
|
|
56
|
+
reasoningTokens?: number;
|
|
57
|
+
};
|
|
58
|
+
export type ToolDefinitionForLLM = {
|
|
59
|
+
type: "function";
|
|
60
|
+
function: {
|
|
61
|
+
name: string;
|
|
62
|
+
description?: string;
|
|
63
|
+
parameters?: Record<string, any>;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
export type ResponseFormat = {
|
|
67
|
+
type: "text";
|
|
68
|
+
} | {
|
|
69
|
+
type: "json";
|
|
70
|
+
schema?: Record<string, any>;
|
|
71
|
+
};
|
|
72
|
+
export type ProviderResponse = {
|
|
73
|
+
content: string | null;
|
|
74
|
+
toolCalls?: ToolCall[];
|
|
75
|
+
usage?: TokenUsage;
|
|
76
|
+
finishReason?: "stop" | "length" | "tool_calls" | "content_filter" | "error";
|
|
77
|
+
};
|
|
78
|
+
export type StreamChunk = {
|
|
79
|
+
type: "content_delta";
|
|
80
|
+
delta: string;
|
|
81
|
+
} | {
|
|
82
|
+
type: "tool_call_start";
|
|
83
|
+
index: number;
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
thought_signature?: string;
|
|
87
|
+
} | {
|
|
88
|
+
type: "tool_call_delta";
|
|
89
|
+
index: number;
|
|
90
|
+
args: string;
|
|
91
|
+
} | {
|
|
92
|
+
type: "tool_call_end";
|
|
93
|
+
index: number;
|
|
94
|
+
} | {
|
|
95
|
+
type: "finish";
|
|
96
|
+
reason: ProviderResponse["finishReason"];
|
|
97
|
+
usage?: TokenUsage;
|
|
98
|
+
} | {
|
|
99
|
+
type: "error";
|
|
100
|
+
error: Error;
|
|
101
|
+
};
|
|
102
|
+
export interface GenerateOptions {
|
|
103
|
+
responseFormat?: ResponseFormat;
|
|
104
|
+
[key: string]: any;
|
|
105
|
+
}
|
|
106
|
+
export interface ModelCapabilities {
|
|
107
|
+
/**
|
|
108
|
+
* File inputs supported by the model/provider.
|
|
109
|
+
* If omitted, the model is assumed to NOT support file parts.
|
|
110
|
+
*/
|
|
111
|
+
inputFiles?: {
|
|
112
|
+
/** Accepted MIME types (exact matches or wildcard like "image/*") */
|
|
113
|
+
mimeTypes: readonly string[] | "any";
|
|
114
|
+
/** Accepted source types */
|
|
115
|
+
sources: ReadonlyArray<FileSource["type"]>;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
export interface IModel {
|
|
119
|
+
providerName: string;
|
|
120
|
+
modelName: string;
|
|
121
|
+
capabilities?: ModelCapabilities;
|
|
122
|
+
/**
|
|
123
|
+
* Gera uma resposta completa (não-streaming)
|
|
124
|
+
*/
|
|
125
|
+
generate(messages: Message[], tools?: ToolDefinitionForLLM[], options?: GenerateOptions): Promise<ProviderResponse>;
|
|
126
|
+
/**
|
|
127
|
+
* Gera uma resposta em streaming
|
|
128
|
+
*/
|
|
129
|
+
generateStream(messages: Message[], tools?: ToolDefinitionForLLM[], options?: GenerateOptions): AsyncGenerator<StreamChunk>;
|
|
130
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Tool } from "../tools/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Interface that all skills must implement.
|
|
4
|
+
*
|
|
5
|
+
* Skills are modular extensions that add tools and optionally modify
|
|
6
|
+
* agent instructions. They encapsulate reusable functionality that can
|
|
7
|
+
* be easily added to agents.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* class MySkill implements ISkill {
|
|
12
|
+
* async getTools(): Promise<Tool[]> {
|
|
13
|
+
* return [
|
|
14
|
+
* new Tool({
|
|
15
|
+
* id: "my_tool",
|
|
16
|
+
* description: "Does something useful",
|
|
17
|
+
* inputSchema: z.object({ query: z.string() }),
|
|
18
|
+
* handler: async (ctx, input) => {
|
|
19
|
+
* return { result: "..." };
|
|
20
|
+
* }
|
|
21
|
+
* })
|
|
22
|
+
* ];
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* async initialize?(): Promise<void> {
|
|
26
|
+
* // Optional: Setup code, validate config, etc.
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* getInstructions?(): string {
|
|
30
|
+
* // Optional: Add skill-specific instructions
|
|
31
|
+
* return "When using my_tool, remember to...";
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export interface ISkill {
|
|
37
|
+
/**
|
|
38
|
+
* Returns the tools provided by this skill.
|
|
39
|
+
* This method is called during agent initialization.
|
|
40
|
+
*
|
|
41
|
+
* @returns Array of Tool instances that this skill provides
|
|
42
|
+
*/
|
|
43
|
+
getTools(): Promise<Tool[]> | Tool[];
|
|
44
|
+
/**
|
|
45
|
+
* Optional initialization method.
|
|
46
|
+
* Called once when the agent is constructed, before tools are registered.
|
|
47
|
+
* Use this for validation, setup, or any async initialization.
|
|
48
|
+
*/
|
|
49
|
+
initialize?(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Optional method to provide additional instructions for the agent.
|
|
52
|
+
* These instructions will be appended to the agent's main instructions.
|
|
53
|
+
*
|
|
54
|
+
* @returns Additional instructions text for the agent
|
|
55
|
+
*/
|
|
56
|
+
getInstructions?(): string | Promise<string>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Helper function to validate that an object implements ISkill
|
|
60
|
+
*/
|
|
61
|
+
export declare function isSkill(obj: any): obj is ISkill;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isSkill = isSkill;
|
|
4
|
+
/**
|
|
5
|
+
* Helper function to validate that an object implements ISkill
|
|
6
|
+
*/
|
|
7
|
+
function isSkill(obj) {
|
|
8
|
+
return obj && typeof obj.getTools === "function";
|
|
9
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ZodSchema } from "zod";
|
|
2
|
+
import { ToolDefinitionForLLM } from "../provider/index.js";
|
|
3
|
+
export type ToolConfig<Input = any, Output = any> = {
|
|
4
|
+
/** Tool identifier (used as function name for LLM) */
|
|
5
|
+
id: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
/** Zod schema for input validation */
|
|
8
|
+
inputSchema?: ZodSchema<Input>;
|
|
9
|
+
/** Alias for inputSchema (for backwards compatibility) */
|
|
10
|
+
parameters?: ZodSchema<Input>;
|
|
11
|
+
handler?: (ctx: any, input: Input) => Promise<Output>;
|
|
12
|
+
};
|
|
13
|
+
export type ToolExecution = {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
input: any;
|
|
17
|
+
output: any;
|
|
18
|
+
durationMs: number;
|
|
19
|
+
error?: string;
|
|
20
|
+
};
|
|
21
|
+
export declare class Tool<Input = any, Output = any> {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
readonly description?: string;
|
|
24
|
+
readonly inputSchema?: ZodSchema<Input>;
|
|
25
|
+
private handler?;
|
|
26
|
+
constructor(config: ToolConfig<Input, Output>);
|
|
27
|
+
/**
|
|
28
|
+
* Converte a tool para o formato esperado pelo LLM
|
|
29
|
+
*/
|
|
30
|
+
toLLMDefinition(): ToolDefinitionForLLM;
|
|
31
|
+
/**
|
|
32
|
+
* Executa a tool com validação de input
|
|
33
|
+
*/
|
|
34
|
+
execute(context: any, input: any): Promise<Output>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Tool = void 0;
|
|
4
|
+
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
5
|
+
// Helper to convert Zod/JSON schema to OpenAI format
|
|
6
|
+
function toJsonSchema(input) {
|
|
7
|
+
const defaultSchema = { type: "object", properties: {}, required: [] };
|
|
8
|
+
if (input && typeof input === "object" && "_def" in input) {
|
|
9
|
+
try {
|
|
10
|
+
const schema = (0, zod_to_json_schema_1.zodToJsonSchema)(input, {
|
|
11
|
+
$refStrategy: "none",
|
|
12
|
+
target: "openApi3",
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
type: "object",
|
|
16
|
+
properties: schema.properties ?? {},
|
|
17
|
+
required: schema.required ?? [],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return defaultSchema;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (input && typeof input === "object" && "type" in input) {
|
|
25
|
+
const obj = input;
|
|
26
|
+
return {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: obj.properties ?? {},
|
|
29
|
+
required: obj.required ?? [],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return defaultSchema;
|
|
33
|
+
}
|
|
34
|
+
class Tool {
|
|
35
|
+
id;
|
|
36
|
+
description;
|
|
37
|
+
inputSchema;
|
|
38
|
+
handler;
|
|
39
|
+
constructor(config) {
|
|
40
|
+
this.id = config.id;
|
|
41
|
+
this.description = config.description;
|
|
42
|
+
// Accept both inputSchema and parameters (parameters is alias)
|
|
43
|
+
this.inputSchema = config.inputSchema ?? config.parameters;
|
|
44
|
+
this.handler = config.handler;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Converte a tool para o formato esperado pelo LLM
|
|
48
|
+
*/
|
|
49
|
+
toLLMDefinition() {
|
|
50
|
+
return {
|
|
51
|
+
type: "function",
|
|
52
|
+
function: {
|
|
53
|
+
name: this.id,
|
|
54
|
+
description: this.description,
|
|
55
|
+
parameters: this.inputSchema ? toJsonSchema(this.inputSchema) : undefined,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Executa a tool com validação de input
|
|
61
|
+
*/
|
|
62
|
+
async execute(context, input) {
|
|
63
|
+
let parsedInput = input;
|
|
64
|
+
// Validate input if schema is present
|
|
65
|
+
if (this.inputSchema) {
|
|
66
|
+
// If input is string (JSON), parse it first
|
|
67
|
+
if (typeof input === "string") {
|
|
68
|
+
try {
|
|
69
|
+
parsedInput = JSON.parse(input);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
throw new Error(`Invalid JSON input for tool ${this.id}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const result = this.inputSchema.safeParse(parsedInput);
|
|
76
|
+
if (!result.success) {
|
|
77
|
+
throw new Error(`Invalid input for tool ${this.id}: ${result.error.message}`);
|
|
78
|
+
}
|
|
79
|
+
parsedInput = result.data;
|
|
80
|
+
}
|
|
81
|
+
if (this.handler) {
|
|
82
|
+
return this.handler(context, parsedInput);
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`Tool ${this.id} has no handler implementation.`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.Tool = Tool;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface AddCostInput {
|
|
2
|
+
amount: number | string;
|
|
3
|
+
description?: string;
|
|
4
|
+
source?: string;
|
|
5
|
+
idempotencyKey?: string;
|
|
6
|
+
metadata?: Record<string, unknown>;
|
|
7
|
+
timestamp?: Date | string;
|
|
8
|
+
correlationId?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function addCost(input: AddCostInput): void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addCost = addCost;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const index_js_1 = require("../domain-events/index.js");
|
|
6
|
+
const index_js_2 = require("../execution-context/index.js");
|
|
7
|
+
const index_js_3 = require("../tracing/index.js");
|
|
8
|
+
function addCost(input) {
|
|
9
|
+
const execContext = index_js_2.ExecutionContext.getOrUndefined();
|
|
10
|
+
if (!execContext) {
|
|
11
|
+
throw new Error("addCost must be called inside an execution context");
|
|
12
|
+
}
|
|
13
|
+
const amount = normalizeAmount(input.amount);
|
|
14
|
+
const timestamp = normalizeTimestamp(input.timestamp);
|
|
15
|
+
const traceContext = index_js_3.Tracing.getContext();
|
|
16
|
+
const payload = {
|
|
17
|
+
amount,
|
|
18
|
+
description: input.description,
|
|
19
|
+
source: input.source,
|
|
20
|
+
idempotencyKey: normalizeIdempotencyKey({
|
|
21
|
+
executionId: execContext.executionId,
|
|
22
|
+
traceId: traceContext?.traceId,
|
|
23
|
+
spanId: traceContext?.spanId,
|
|
24
|
+
timestamp,
|
|
25
|
+
amount,
|
|
26
|
+
description: input.description,
|
|
27
|
+
source: input.source,
|
|
28
|
+
metadata: input.metadata,
|
|
29
|
+
}, input.idempotencyKey),
|
|
30
|
+
metadata: input.metadata,
|
|
31
|
+
};
|
|
32
|
+
const fullEvent = {
|
|
33
|
+
type: "execution:cost:incurred",
|
|
34
|
+
timestamp,
|
|
35
|
+
trace: {
|
|
36
|
+
traceId: traceContext?.traceId ?? `fallback-${Date.now()}`,
|
|
37
|
+
spanId: traceContext?.spanId ?? `fallback-${Date.now()}`,
|
|
38
|
+
parentSpanId: traceContext?.parentId,
|
|
39
|
+
},
|
|
40
|
+
correlationId: input.correlationId,
|
|
41
|
+
executionId: execContext.executionId,
|
|
42
|
+
rootExecutionId: execContext.rootExecutionId,
|
|
43
|
+
parentExecutionId: execContext.parentExecutionId,
|
|
44
|
+
data: payload,
|
|
45
|
+
};
|
|
46
|
+
index_js_1.DomainEvents.publish(fullEvent);
|
|
47
|
+
}
|
|
48
|
+
function normalizeAmount(value) {
|
|
49
|
+
if (typeof value === "number") {
|
|
50
|
+
if (!Number.isFinite(value)) {
|
|
51
|
+
throw new Error("addCost amount must be a finite number");
|
|
52
|
+
}
|
|
53
|
+
return value.toString();
|
|
54
|
+
}
|
|
55
|
+
const trimmed = value.trim();
|
|
56
|
+
if (!trimmed) {
|
|
57
|
+
throw new Error("addCost amount is required");
|
|
58
|
+
}
|
|
59
|
+
const parsed = Number(trimmed);
|
|
60
|
+
if (!Number.isFinite(parsed)) {
|
|
61
|
+
throw new Error("addCost amount must be numeric");
|
|
62
|
+
}
|
|
63
|
+
return trimmed;
|
|
64
|
+
}
|
|
65
|
+
function normalizeTimestamp(value) {
|
|
66
|
+
if (!value)
|
|
67
|
+
return new Date().toISOString();
|
|
68
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
69
|
+
if (Number.isNaN(date.getTime())) {
|
|
70
|
+
throw new Error("addCost timestamp is invalid");
|
|
71
|
+
}
|
|
72
|
+
return date.toISOString();
|
|
73
|
+
}
|
|
74
|
+
function normalizeIdempotencyKey(payload, provided) {
|
|
75
|
+
const trimmed = provided?.trim();
|
|
76
|
+
if (trimmed)
|
|
77
|
+
return trimmed;
|
|
78
|
+
const raw = JSON.stringify(payload);
|
|
79
|
+
return (0, node_crypto_1.createHash)("sha256").update(raw).digest("hex");
|
|
80
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const add_cost_js_1 = require("./add-cost.js");
|
|
4
|
+
const index_js_1 = require("../domain-events/index.js");
|
|
5
|
+
const index_js_2 = require("../execution-context/index.js");
|
|
6
|
+
const schemas_js_1 = require("../events/schemas.js");
|
|
7
|
+
class CapturingExporter {
|
|
8
|
+
events = [];
|
|
9
|
+
async exportBatch(events) {
|
|
10
|
+
this.events.push(...events);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
describe("addCost", () => {
|
|
14
|
+
it("should publish a valid execution cost event using context ids", async () => {
|
|
15
|
+
const exporter = new CapturingExporter();
|
|
16
|
+
index_js_1.DomainEvents.setExporter(exporter);
|
|
17
|
+
await index_js_2.ExecutionContext.run({ executionId: "exec-123", rootExecutionId: "exec-123" }, async () => {
|
|
18
|
+
(0, add_cost_js_1.addCost)({ amount: 0.05, description: "LLM usage" });
|
|
19
|
+
});
|
|
20
|
+
expect(exporter.events.length).toBe(1);
|
|
21
|
+
const event = exporter.events[0];
|
|
22
|
+
const parsed = schemas_js_1.NebulaEventSchema.safeParse(event);
|
|
23
|
+
expect(parsed.success).toBe(true);
|
|
24
|
+
if (!parsed.success)
|
|
25
|
+
return;
|
|
26
|
+
expect(parsed.data.type).toBe("execution:cost:incurred");
|
|
27
|
+
const costEvent = parsed.data;
|
|
28
|
+
expect(costEvent.executionId).toBe("exec-123");
|
|
29
|
+
expect(costEvent.rootExecutionId).toBe("exec-123");
|
|
30
|
+
expect(costEvent.data.amount).toBe("0.05");
|
|
31
|
+
expect(costEvent.data.description).toBe("LLM usage");
|
|
32
|
+
});
|
|
33
|
+
it("should throw when called outside execution context", () => {
|
|
34
|
+
expect(() => (0, add_cost_js_1.addCost)({ amount: "1" })).toThrow("addCost must be called inside an execution context");
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./add-cost.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./add-cost.js"), exports);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { NebulaEvent } from "../events/schemas.js";
|
|
2
|
+
export interface IDomainEventsExporter {
|
|
3
|
+
exportBatch(events: NebulaEvent[]): Promise<void>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Best-effort domain event exporter.
|
|
7
|
+
*
|
|
8
|
+
* Observability (spans) is handled by `Tracing` and `ITelemetryExporter`.
|
|
9
|
+
* Domain events are separate and meant for materialization / execution indexing.
|
|
10
|
+
*/
|
|
11
|
+
export declare class DomainEvents {
|
|
12
|
+
private static exporter;
|
|
13
|
+
static setExporter(exporter: IDomainEventsExporter): void;
|
|
14
|
+
static publish(event: NebulaEvent): void;
|
|
15
|
+
static publishBatch(events: NebulaEvent[]): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DomainEvents = void 0;
|
|
4
|
+
class NoopDomainEventsExporter {
|
|
5
|
+
async exportBatch(_events) {
|
|
6
|
+
// noop
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Best-effort domain event exporter.
|
|
11
|
+
*
|
|
12
|
+
* Observability (spans) is handled by `Tracing` and `ITelemetryExporter`.
|
|
13
|
+
* Domain events are separate and meant for materialization / execution indexing.
|
|
14
|
+
*/
|
|
15
|
+
class DomainEvents {
|
|
16
|
+
static exporter = new NoopDomainEventsExporter();
|
|
17
|
+
static setExporter(exporter) {
|
|
18
|
+
this.exporter = exporter;
|
|
19
|
+
}
|
|
20
|
+
static publish(event) {
|
|
21
|
+
// Fire-and-forget; must never break execution paths.
|
|
22
|
+
try {
|
|
23
|
+
void this.exporter.exportBatch([event]);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// ignore
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
static publishBatch(events) {
|
|
30
|
+
try {
|
|
31
|
+
void this.exporter.exportBatch(events);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// ignore
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.DomainEvents = DomainEvents;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type EvaluationResult = {
|
|
2
|
+
score: number;
|
|
3
|
+
passed: boolean;
|
|
4
|
+
reason?: string;
|
|
5
|
+
metadata?: Record<string, any>;
|
|
6
|
+
};
|
|
7
|
+
export interface IScorer {
|
|
8
|
+
name: string;
|
|
9
|
+
evaluate(input: string, output: string, expected?: string): Promise<EvaluationResult>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Exemplo simples de Scorer: Valida se o output contém certas palavras-chave
|
|
13
|
+
*/
|
|
14
|
+
export declare class KeywordScorer implements IScorer {
|
|
15
|
+
private keywords;
|
|
16
|
+
name: string;
|
|
17
|
+
constructor(keywords: string[]);
|
|
18
|
+
evaluate(input: string, output: string): Promise<EvaluationResult>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KeywordScorer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Exemplo simples de Scorer: Valida se o output contém certas palavras-chave
|
|
6
|
+
*/
|
|
7
|
+
class KeywordScorer {
|
|
8
|
+
keywords;
|
|
9
|
+
name = "KeywordScorer";
|
|
10
|
+
constructor(keywords) {
|
|
11
|
+
this.keywords = keywords;
|
|
12
|
+
}
|
|
13
|
+
async evaluate(input, output) {
|
|
14
|
+
const lowerOutput = output.toLowerCase();
|
|
15
|
+
const found = this.keywords.filter(k => lowerOutput.includes(k.toLowerCase()));
|
|
16
|
+
const score = found.length / this.keywords.length;
|
|
17
|
+
return {
|
|
18
|
+
score,
|
|
19
|
+
passed: score === 1,
|
|
20
|
+
reason: `Found ${found.length}/${this.keywords.length} keywords: ${found.join(", ")}`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.KeywordScorer = KeywordScorer;
|