confused-ai-core 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/FEATURES.md +169 -0
- package/package.json +119 -0
- package/src/agent.ts +187 -0
- package/src/agentic/index.ts +87 -0
- package/src/agentic/runner.ts +386 -0
- package/src/agentic/types.ts +91 -0
- package/src/artifacts/artifact.ts +417 -0
- package/src/artifacts/index.ts +42 -0
- package/src/artifacts/media.ts +304 -0
- package/src/cli/index.ts +122 -0
- package/src/core/base-agent.ts +151 -0
- package/src/core/context-builder.ts +106 -0
- package/src/core/index.ts +8 -0
- package/src/core/schemas.ts +17 -0
- package/src/core/types.ts +158 -0
- package/src/create-agent.ts +309 -0
- package/src/debug-logger.ts +188 -0
- package/src/dx/agent.ts +88 -0
- package/src/dx/define-agent.ts +183 -0
- package/src/dx/dev-logger.ts +57 -0
- package/src/dx/index.ts +11 -0
- package/src/errors.ts +175 -0
- package/src/execution/engine.ts +522 -0
- package/src/execution/graph-builder.ts +362 -0
- package/src/execution/index.ts +8 -0
- package/src/execution/types.ts +257 -0
- package/src/execution/worker-pool.ts +308 -0
- package/src/extensions/index.ts +123 -0
- package/src/guardrails/allowlist.ts +155 -0
- package/src/guardrails/index.ts +17 -0
- package/src/guardrails/types.ts +159 -0
- package/src/guardrails/validator.ts +265 -0
- package/src/index.ts +74 -0
- package/src/knowledge/index.ts +5 -0
- package/src/knowledge/types.ts +52 -0
- package/src/learning/in-memory-store.ts +72 -0
- package/src/learning/index.ts +6 -0
- package/src/learning/types.ts +42 -0
- package/src/llm/cache.ts +300 -0
- package/src/llm/index.ts +22 -0
- package/src/llm/model-resolver.ts +81 -0
- package/src/llm/openai-provider.ts +313 -0
- package/src/llm/openrouter-provider.ts +29 -0
- package/src/llm/types.ts +131 -0
- package/src/memory/in-memory-store.ts +255 -0
- package/src/memory/index.ts +7 -0
- package/src/memory/types.ts +193 -0
- package/src/memory/vector-store.ts +251 -0
- package/src/observability/console-logger.ts +123 -0
- package/src/observability/index.ts +12 -0
- package/src/observability/metrics.ts +85 -0
- package/src/observability/otlp-exporter.ts +417 -0
- package/src/observability/tracer.ts +105 -0
- package/src/observability/types.ts +341 -0
- package/src/orchestration/agent-adapter.ts +33 -0
- package/src/orchestration/index.ts +34 -0
- package/src/orchestration/load-balancer.ts +151 -0
- package/src/orchestration/mcp-types.ts +59 -0
- package/src/orchestration/message-bus.ts +192 -0
- package/src/orchestration/orchestrator.ts +349 -0
- package/src/orchestration/pipeline.ts +66 -0
- package/src/orchestration/supervisor.ts +107 -0
- package/src/orchestration/swarm.ts +1099 -0
- package/src/orchestration/toolkit.ts +47 -0
- package/src/orchestration/types.ts +339 -0
- package/src/planner/classical-planner.ts +383 -0
- package/src/planner/index.ts +8 -0
- package/src/planner/llm-planner.ts +353 -0
- package/src/planner/types.ts +227 -0
- package/src/planner/validator.ts +297 -0
- package/src/production/circuit-breaker.ts +290 -0
- package/src/production/graceful-shutdown.ts +251 -0
- package/src/production/health.ts +333 -0
- package/src/production/index.ts +57 -0
- package/src/production/latency-eval.ts +62 -0
- package/src/production/rate-limiter.ts +287 -0
- package/src/production/resumable-stream.ts +289 -0
- package/src/production/types.ts +81 -0
- package/src/sdk/index.ts +374 -0
- package/src/session/db-driver.ts +50 -0
- package/src/session/in-memory-store.ts +235 -0
- package/src/session/index.ts +12 -0
- package/src/session/sql-store.ts +315 -0
- package/src/session/sqlite-store.ts +61 -0
- package/src/session/types.ts +153 -0
- package/src/tools/base-tool.ts +223 -0
- package/src/tools/browser-tool.ts +123 -0
- package/src/tools/calculator-tool.ts +265 -0
- package/src/tools/file-tools.ts +394 -0
- package/src/tools/github-tool.ts +432 -0
- package/src/tools/hackernews-tool.ts +187 -0
- package/src/tools/http-tool.ts +118 -0
- package/src/tools/index.ts +99 -0
- package/src/tools/jira-tool.ts +373 -0
- package/src/tools/notion-tool.ts +322 -0
- package/src/tools/openai-tool.ts +236 -0
- package/src/tools/registry.ts +131 -0
- package/src/tools/serpapi-tool.ts +234 -0
- package/src/tools/shell-tool.ts +118 -0
- package/src/tools/slack-tool.ts +327 -0
- package/src/tools/telegram-tool.ts +127 -0
- package/src/tools/types.ts +229 -0
- package/src/tools/websearch-tool.ts +335 -0
- package/src/tools/wikipedia-tool.ts +177 -0
- package/src/tools/yfinance-tool.ts +33 -0
- package/src/voice/index.ts +17 -0
- package/src/voice/voice-provider.ts +228 -0
- package/tests/artifact.test.ts +241 -0
- package/tests/circuit-breaker.test.ts +171 -0
- package/tests/health.test.ts +192 -0
- package/tests/llm-cache.test.ts +186 -0
- package/tests/rate-limiter.test.ts +161 -0
- package/tsconfig.json +29 -0
- package/vitest.config.ts +47 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardrails types and interfaces
|
|
3
|
+
*
|
|
4
|
+
* Provides output validation, allowlists, and safety controls for agent outputs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Guardrail check result
|
|
11
|
+
*/
|
|
12
|
+
export interface GuardrailResult {
|
|
13
|
+
readonly passed: boolean;
|
|
14
|
+
readonly rule: string;
|
|
15
|
+
readonly message?: string;
|
|
16
|
+
readonly details?: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Guardrail violation
|
|
21
|
+
*/
|
|
22
|
+
export interface GuardrailViolation {
|
|
23
|
+
readonly rule: string;
|
|
24
|
+
readonly message: string;
|
|
25
|
+
readonly severity: 'error' | 'warning';
|
|
26
|
+
readonly details?: unknown;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Guardrail check context
|
|
31
|
+
*/
|
|
32
|
+
export interface GuardrailContext {
|
|
33
|
+
readonly agentId: string;
|
|
34
|
+
readonly sessionId?: string;
|
|
35
|
+
readonly toolName?: string;
|
|
36
|
+
readonly toolArgs?: Record<string, unknown>;
|
|
37
|
+
readonly output?: unknown;
|
|
38
|
+
readonly metadata?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Guardrail rule interface
|
|
43
|
+
*/
|
|
44
|
+
export interface GuardrailRule {
|
|
45
|
+
readonly name: string;
|
|
46
|
+
readonly description: string;
|
|
47
|
+
readonly severity: 'error' | 'warning';
|
|
48
|
+
check(context: GuardrailContext): GuardrailResult | Promise<GuardrailResult>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Output validation rule using Zod schema
|
|
53
|
+
*/
|
|
54
|
+
export interface SchemaValidationRule<T = unknown> {
|
|
55
|
+
readonly name: string;
|
|
56
|
+
readonly schema: z.ZodType<T>;
|
|
57
|
+
readonly description?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Allowlist configuration
|
|
62
|
+
*/
|
|
63
|
+
export interface AllowlistConfig {
|
|
64
|
+
readonly allowedTools?: string[];
|
|
65
|
+
readonly allowedHosts?: string[];
|
|
66
|
+
readonly allowedPaths?: string[];
|
|
67
|
+
readonly allowedOutputs?: string[];
|
|
68
|
+
readonly blockedPatterns?: RegExp[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Guardrail configuration
|
|
73
|
+
*/
|
|
74
|
+
export interface GuardrailsConfig {
|
|
75
|
+
readonly enabled?: boolean;
|
|
76
|
+
readonly rules?: GuardrailRule[];
|
|
77
|
+
readonly schemaValidations?: SchemaValidationRule[];
|
|
78
|
+
readonly allowlist?: AllowlistConfig;
|
|
79
|
+
readonly onViolation?: (violation: GuardrailViolation, context: GuardrailContext) => void | Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Guardrail engine interface
|
|
84
|
+
*/
|
|
85
|
+
export interface GuardrailEngine {
|
|
86
|
+
/**
|
|
87
|
+
* Check if a tool call is allowed
|
|
88
|
+
*/
|
|
89
|
+
checkToolCall(toolName: string, args: Record<string, unknown>, context: GuardrailContext): Promise<GuardrailResult[]>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Validate output against schemas
|
|
93
|
+
*/
|
|
94
|
+
validateOutput(output: unknown, context: GuardrailContext): Promise<GuardrailResult[]>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Run all guardrail checks
|
|
98
|
+
*/
|
|
99
|
+
checkAll(context: GuardrailContext): Promise<GuardrailResult[]>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get all violations from results
|
|
103
|
+
*/
|
|
104
|
+
getViolations(results: GuardrailResult[]): GuardrailViolation[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Human-in-the-loop hook types
|
|
109
|
+
*/
|
|
110
|
+
export interface HumanInTheLoopHooks {
|
|
111
|
+
/**
|
|
112
|
+
* Called before executing a tool - can pause for approval
|
|
113
|
+
* Return true to allow, false to block, or throw to abort
|
|
114
|
+
*/
|
|
115
|
+
beforeToolCall?: (
|
|
116
|
+
toolName: string,
|
|
117
|
+
args: Record<string, unknown>,
|
|
118
|
+
context: GuardrailContext
|
|
119
|
+
) => Promise<boolean> | boolean;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Called before finishing the run - can pause for review
|
|
123
|
+
* Return true to allow finish, false to continue, or throw to abort
|
|
124
|
+
*/
|
|
125
|
+
beforeFinish?: (
|
|
126
|
+
output: unknown,
|
|
127
|
+
context: GuardrailContext
|
|
128
|
+
) => Promise<boolean> | boolean;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Called on guardrail violation
|
|
132
|
+
*/
|
|
133
|
+
onViolation?: (violation: GuardrailViolation, context: GuardrailContext) => void | Promise<void>;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Approval request for human-in-the-loop
|
|
138
|
+
*/
|
|
139
|
+
export interface ApprovalRequest {
|
|
140
|
+
readonly id: string;
|
|
141
|
+
readonly type: 'tool_call' | 'finish';
|
|
142
|
+
readonly context: GuardrailContext;
|
|
143
|
+
readonly data: {
|
|
144
|
+
toolName?: string;
|
|
145
|
+
args?: Record<string, unknown>;
|
|
146
|
+
output?: unknown;
|
|
147
|
+
};
|
|
148
|
+
readonly requestedAt: Date;
|
|
149
|
+
readonly timeoutMs?: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Approval response
|
|
154
|
+
*/
|
|
155
|
+
export interface ApprovalResponse {
|
|
156
|
+
readonly approved: boolean;
|
|
157
|
+
readonly reason?: string;
|
|
158
|
+
readonly modifiedArgs?: Record<string, unknown>;
|
|
159
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardrail validator implementation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
GuardrailEngine,
|
|
7
|
+
GuardrailRule,
|
|
8
|
+
GuardrailResult,
|
|
9
|
+
GuardrailViolation,
|
|
10
|
+
GuardrailContext,
|
|
11
|
+
GuardrailsConfig,
|
|
12
|
+
SchemaValidationRule,
|
|
13
|
+
} from './types.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Default guardrail engine implementation
|
|
17
|
+
*/
|
|
18
|
+
export class GuardrailValidator implements GuardrailEngine {
|
|
19
|
+
private rules: GuardrailRule[];
|
|
20
|
+
private schemaValidations: SchemaValidationRule[];
|
|
21
|
+
private onViolation?: (violation: GuardrailViolation, context: GuardrailContext) => void | Promise<void>;
|
|
22
|
+
|
|
23
|
+
constructor(config: GuardrailsConfig = {}) {
|
|
24
|
+
this.rules = config.rules ?? [];
|
|
25
|
+
this.schemaValidations = config.schemaValidations ?? [];
|
|
26
|
+
this.onViolation = config.onViolation;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Add a rule to the validator
|
|
31
|
+
*/
|
|
32
|
+
addRule(rule: GuardrailRule): void {
|
|
33
|
+
this.rules.push(rule);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Add a schema validation
|
|
38
|
+
*/
|
|
39
|
+
addSchemaValidation<T>(validation: SchemaValidationRule<T>): void {
|
|
40
|
+
this.schemaValidations.push(validation);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if a tool call is allowed
|
|
45
|
+
*/
|
|
46
|
+
async checkToolCall(
|
|
47
|
+
toolName: string,
|
|
48
|
+
args: Record<string, unknown>,
|
|
49
|
+
context: GuardrailContext
|
|
50
|
+
): Promise<GuardrailResult[]> {
|
|
51
|
+
const ctx: GuardrailContext = {
|
|
52
|
+
...context,
|
|
53
|
+
toolName,
|
|
54
|
+
toolArgs: args,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const results: GuardrailResult[] = [];
|
|
58
|
+
for (const rule of this.rules) {
|
|
59
|
+
try {
|
|
60
|
+
const result = await rule.check(ctx);
|
|
61
|
+
results.push(result);
|
|
62
|
+
if (!result.passed && this.onViolation) {
|
|
63
|
+
await this.onViolation(
|
|
64
|
+
{
|
|
65
|
+
rule: rule.name,
|
|
66
|
+
message: result.message ?? 'Guardrail check failed',
|
|
67
|
+
severity: rule.severity,
|
|
68
|
+
details: result.details,
|
|
69
|
+
},
|
|
70
|
+
ctx
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
results.push({
|
|
75
|
+
passed: false,
|
|
76
|
+
rule: rule.name,
|
|
77
|
+
message: error instanceof Error ? error.message : String(error),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return results;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Validate output against schemas
|
|
87
|
+
*/
|
|
88
|
+
async validateOutput(output: unknown, context: GuardrailContext): Promise<GuardrailResult[]> {
|
|
89
|
+
const results: GuardrailResult[] = [];
|
|
90
|
+
|
|
91
|
+
for (const validation of this.schemaValidations) {
|
|
92
|
+
try {
|
|
93
|
+
validation.schema.parse(output);
|
|
94
|
+
results.push({
|
|
95
|
+
passed: true,
|
|
96
|
+
rule: validation.name,
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
100
|
+
results.push({
|
|
101
|
+
passed: false,
|
|
102
|
+
rule: validation.name,
|
|
103
|
+
message: `Schema validation failed: ${message}`,
|
|
104
|
+
details: error,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (this.onViolation) {
|
|
108
|
+
await this.onViolation(
|
|
109
|
+
{
|
|
110
|
+
rule: validation.name,
|
|
111
|
+
message,
|
|
112
|
+
severity: 'error',
|
|
113
|
+
details: error,
|
|
114
|
+
},
|
|
115
|
+
{ ...context, output }
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return results;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Run all guardrail checks
|
|
126
|
+
*/
|
|
127
|
+
async checkAll(context: GuardrailContext): Promise<GuardrailResult[]> {
|
|
128
|
+
const results: GuardrailResult[] = [];
|
|
129
|
+
|
|
130
|
+
// Check tool call if present
|
|
131
|
+
if (context.toolName) {
|
|
132
|
+
const toolResults = await this.checkToolCall(
|
|
133
|
+
context.toolName,
|
|
134
|
+
context.toolArgs ?? {},
|
|
135
|
+
context
|
|
136
|
+
);
|
|
137
|
+
results.push(...toolResults);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Validate output if present
|
|
141
|
+
if (context.output !== undefined) {
|
|
142
|
+
const outputResults = await this.validateOutput(context.output, context);
|
|
143
|
+
results.push(...outputResults);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Run general rules
|
|
147
|
+
for (const rule of this.rules) {
|
|
148
|
+
try {
|
|
149
|
+
const result = await rule.check(context);
|
|
150
|
+
results.push(result);
|
|
151
|
+
if (!result.passed && this.onViolation) {
|
|
152
|
+
await this.onViolation(
|
|
153
|
+
{
|
|
154
|
+
rule: rule.name,
|
|
155
|
+
message: result.message ?? 'Guardrail check failed',
|
|
156
|
+
severity: rule.severity,
|
|
157
|
+
details: result.details,
|
|
158
|
+
},
|
|
159
|
+
context
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
results.push({
|
|
164
|
+
passed: false,
|
|
165
|
+
rule: rule.name,
|
|
166
|
+
message: error instanceof Error ? error.message : String(error),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return results;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get all violations from results
|
|
176
|
+
*/
|
|
177
|
+
getViolations(results: GuardrailResult[]): GuardrailViolation[] {
|
|
178
|
+
return results
|
|
179
|
+
.filter(r => !r.passed)
|
|
180
|
+
.map(r => ({
|
|
181
|
+
rule: r.rule,
|
|
182
|
+
message: r.message ?? 'Guardrail check failed',
|
|
183
|
+
severity: 'error',
|
|
184
|
+
details: r.details,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Create a regex-based content guardrail rule
|
|
191
|
+
*/
|
|
192
|
+
export function createContentRule(
|
|
193
|
+
name: string,
|
|
194
|
+
description: string,
|
|
195
|
+
pattern: RegExp,
|
|
196
|
+
severity: 'error' | 'warning' = 'error'
|
|
197
|
+
): GuardrailRule {
|
|
198
|
+
return {
|
|
199
|
+
name,
|
|
200
|
+
description,
|
|
201
|
+
severity,
|
|
202
|
+
check(context: GuardrailContext): GuardrailResult {
|
|
203
|
+
const raw = context.output;
|
|
204
|
+
const content =
|
|
205
|
+
typeof raw === 'string' ? raw : raw === undefined || raw === null ? '' : JSON.stringify(raw);
|
|
206
|
+
|
|
207
|
+
const matches = pattern.test(content);
|
|
208
|
+
return {
|
|
209
|
+
passed: !matches,
|
|
210
|
+
rule: name,
|
|
211
|
+
message: matches ? `Content matched forbidden pattern: ${pattern}` : undefined,
|
|
212
|
+
};
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Create a tool allowlist rule
|
|
219
|
+
*/
|
|
220
|
+
export function createToolAllowlistRule(allowedTools: string[]): GuardrailRule {
|
|
221
|
+
return {
|
|
222
|
+
name: 'tool_allowlist',
|
|
223
|
+
description: `Only allow tools: ${allowedTools.join(', ')}`,
|
|
224
|
+
severity: 'error',
|
|
225
|
+
check(context: GuardrailContext): GuardrailResult {
|
|
226
|
+
if (!context.toolName) {
|
|
227
|
+
return { passed: true, rule: 'tool_allowlist' };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const allowed = allowedTools.includes(context.toolName);
|
|
231
|
+
return {
|
|
232
|
+
passed: allowed,
|
|
233
|
+
rule: 'tool_allowlist',
|
|
234
|
+
message: allowed ? undefined : `Tool '${context.toolName}' is not in the allowlist`,
|
|
235
|
+
};
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Create a maximum length rule
|
|
242
|
+
*/
|
|
243
|
+
export function createMaxLengthRule(
|
|
244
|
+
name: string,
|
|
245
|
+
maxLength: number,
|
|
246
|
+
severity: 'error' | 'warning' = 'error'
|
|
247
|
+
): GuardrailRule {
|
|
248
|
+
return {
|
|
249
|
+
name,
|
|
250
|
+
description: `Maximum length: ${maxLength}`,
|
|
251
|
+
severity,
|
|
252
|
+
check(context: GuardrailContext): GuardrailResult {
|
|
253
|
+
const raw = context.output;
|
|
254
|
+
const content =
|
|
255
|
+
typeof raw === 'string' ? raw : raw === undefined || raw === null ? '' : JSON.stringify(raw);
|
|
256
|
+
|
|
257
|
+
const withinLimit = content.length <= maxLength;
|
|
258
|
+
return {
|
|
259
|
+
passed: withinLimit,
|
|
260
|
+
rule: name,
|
|
261
|
+
message: withinLimit ? undefined : `Output exceeds maximum length of ${maxLength}`,
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Framework - A production-grade TypeScript agent framework
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Core exports
|
|
8
|
+
export * from './core/index.js';
|
|
9
|
+
|
|
10
|
+
// Memory exports
|
|
11
|
+
export * from './memory/index.js';
|
|
12
|
+
|
|
13
|
+
// Tools exports
|
|
14
|
+
export * from './tools/index.js';
|
|
15
|
+
|
|
16
|
+
// Planner exports
|
|
17
|
+
export * from './planner/index.js';
|
|
18
|
+
|
|
19
|
+
// Execution exports
|
|
20
|
+
export * from './execution/index.js';
|
|
21
|
+
|
|
22
|
+
// Orchestration exports
|
|
23
|
+
export * from './orchestration/index.js';
|
|
24
|
+
|
|
25
|
+
// Observability exports
|
|
26
|
+
export * from './observability/index.js';
|
|
27
|
+
|
|
28
|
+
// LLM provider abstraction (optional peer: openai for OpenAIProvider)
|
|
29
|
+
export * from './llm/index.js';
|
|
30
|
+
|
|
31
|
+
// Agentic loop (ReAct-style)
|
|
32
|
+
export * from './agentic/index.js';
|
|
33
|
+
|
|
34
|
+
// SDK exports
|
|
35
|
+
export * from './sdk/index.js';
|
|
36
|
+
|
|
37
|
+
// Session exports
|
|
38
|
+
export * from './session/index.js';
|
|
39
|
+
|
|
40
|
+
// Guardrails exports
|
|
41
|
+
export * from './guardrails/index.js';
|
|
42
|
+
|
|
43
|
+
// Learning: user profiles, memories across sessions, learning modes (always / agentic)
|
|
44
|
+
export * from './learning/index.js';
|
|
45
|
+
|
|
46
|
+
// Knowledge: RAG, hybrid search, reranking, persistent session/state
|
|
47
|
+
export * from './knowledge/index.js';
|
|
48
|
+
|
|
49
|
+
// Production: runtime, control plane, evals (accuracy, performance, latency)
|
|
50
|
+
export * from './production/index.js';
|
|
51
|
+
|
|
52
|
+
// Structured errors for production (ErrorCode, AgentError, LLMError, ToolExecutionError, etc.)
|
|
53
|
+
export * from './errors.js';
|
|
54
|
+
|
|
55
|
+
// Extensions: plug any DB, tools, cross-tool middleware; wrap agents for Orchestrator/Pipeline
|
|
56
|
+
export * from './extensions/index.js';
|
|
57
|
+
|
|
58
|
+
// One-line production agent (auto LLM, memory, tools, session, guardrails)
|
|
59
|
+
export {
|
|
60
|
+
createAgent,
|
|
61
|
+
type CreateAgentOptions,
|
|
62
|
+
type CreateAgentResult,
|
|
63
|
+
type AgentRunOptions,
|
|
64
|
+
} from './create-agent.js';
|
|
65
|
+
|
|
66
|
+
// Agno-style Agent class: clean process, run anytime (model, db, learning, tools)
|
|
67
|
+
export { Agent, type AgentOptions } from './agent.js';
|
|
68
|
+
|
|
69
|
+
// Best DX: minimal agent(), fluent defineAgent(), dev logging
|
|
70
|
+
export { agent, defineAgent, createDevLogger, createDevToolMiddleware } from './dx/index.js';
|
|
71
|
+
export type { AgentMinimalOptions, DefineAgentOptions } from './dx/index.js';
|
|
72
|
+
|
|
73
|
+
// Version
|
|
74
|
+
export const VERSION = '1.0.0';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Knowledge: agentic RAG, hybrid search, reranking, persistent session/state.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { EntityId } from '../core/types.js';
|
|
6
|
+
|
|
7
|
+
/** Single retrieved chunk for RAG */
|
|
8
|
+
export interface RAGChunk {
|
|
9
|
+
readonly id: EntityId;
|
|
10
|
+
readonly content: string;
|
|
11
|
+
readonly score: number;
|
|
12
|
+
readonly metadata?: Record<string, unknown>;
|
|
13
|
+
readonly source?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** RAG query options */
|
|
17
|
+
export interface RAGQueryOptions {
|
|
18
|
+
readonly limit?: number;
|
|
19
|
+
readonly threshold?: number;
|
|
20
|
+
readonly filter?: Record<string, unknown>;
|
|
21
|
+
readonly rerank?: boolean;
|
|
22
|
+
readonly hybrid?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** RAG query result */
|
|
26
|
+
export interface RAGQueryResult {
|
|
27
|
+
readonly chunks: RAGChunk[];
|
|
28
|
+
readonly query: string;
|
|
29
|
+
readonly totalRetrieved?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** RAG engine: retrieve (and optionally generate). Plug 20+ vector stores, hybrid search, reranking. */
|
|
33
|
+
export interface RAGEngine {
|
|
34
|
+
/** Retrieve relevant chunks for a query (vector + optional keyword + rerank) */
|
|
35
|
+
retrieve(query: string, options?: RAGQueryOptions): Promise<RAGQueryResult>;
|
|
36
|
+
|
|
37
|
+
/** Optional: generate answer from query + retrieved context (agentic RAG) */
|
|
38
|
+
generate?(query: string, options?: RAGQueryOptions & { maxTokens?: number }): Promise<{ answer: string; chunks: RAGChunk[] }>;
|
|
39
|
+
|
|
40
|
+
/** Ingest documents/chunks for later retrieval */
|
|
41
|
+
ingest?(chunks: Array<{ content: string; metadata?: Record<string, unknown> }>): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Hybrid search: combine vector similarity + keyword (e.g. BM25). */
|
|
45
|
+
export interface HybridSearchProvider {
|
|
46
|
+
search(query: string, limit: number, filter?: Record<string, unknown>): Promise<RAGChunk[]>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Reranker: score and reorder retrieved chunks. */
|
|
50
|
+
export interface RerankerProvider {
|
|
51
|
+
rerank(query: string, chunks: RAGChunk[], topK?: number): Promise<RAGChunk[]>;
|
|
52
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory user profile store (default; plug SQLite/Postgres for production).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { EntityId } from '../core/types.js';
|
|
6
|
+
import type { UserProfile, UserProfileQuery } from './types.js';
|
|
7
|
+
|
|
8
|
+
export class InMemoryUserProfileStore {
|
|
9
|
+
private profiles = new Map<string, UserProfile>();
|
|
10
|
+
|
|
11
|
+
private key(userId: string, agentId?: EntityId): string {
|
|
12
|
+
return agentId ? `${userId}:${agentId}` : userId;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async get(userId: string, agentId?: EntityId): Promise<UserProfile | null> {
|
|
16
|
+
return this.profiles.get(this.key(userId, agentId)) ?? null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async set(profile: Omit<UserProfile, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserProfile> {
|
|
20
|
+
const now = new Date();
|
|
21
|
+
const id = `profile-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
22
|
+
const entry: UserProfile = {
|
|
23
|
+
...profile,
|
|
24
|
+
id,
|
|
25
|
+
createdAt: now,
|
|
26
|
+
updatedAt: now,
|
|
27
|
+
};
|
|
28
|
+
this.profiles.set(this.key(profile.userId, profile.agentId), entry);
|
|
29
|
+
return entry;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async update(
|
|
33
|
+
userId: string,
|
|
34
|
+
updates: Partial<Omit<UserProfile, 'id' | 'userId' | 'createdAt'>>,
|
|
35
|
+
agentId?: EntityId
|
|
36
|
+
): Promise<UserProfile> {
|
|
37
|
+
const existing = await this.get(userId, agentId);
|
|
38
|
+
if (!existing) {
|
|
39
|
+
const now = new Date();
|
|
40
|
+
const entry: UserProfile = {
|
|
41
|
+
id: `profile-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
42
|
+
userId,
|
|
43
|
+
agentId,
|
|
44
|
+
metadata: (updates.metadata as Record<string, unknown>) ?? {},
|
|
45
|
+
createdAt: now,
|
|
46
|
+
updatedAt: now,
|
|
47
|
+
...updates,
|
|
48
|
+
};
|
|
49
|
+
this.profiles.set(this.key(userId, agentId), entry);
|
|
50
|
+
return entry;
|
|
51
|
+
}
|
|
52
|
+
const updated: UserProfile = {
|
|
53
|
+
...existing,
|
|
54
|
+
...updates,
|
|
55
|
+
updatedAt: new Date(),
|
|
56
|
+
};
|
|
57
|
+
this.profiles.set(this.key(userId, agentId), updated);
|
|
58
|
+
return updated;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async list(query?: UserProfileQuery): Promise<UserProfile[]> {
|
|
62
|
+
let list = Array.from(this.profiles.values());
|
|
63
|
+
if (query?.userId) list = list.filter(p => p.userId === query.userId);
|
|
64
|
+
if (query?.agentId) list = list.filter(p => p.agentId === query.agentId);
|
|
65
|
+
if (query?.limit) list = list.slice(0, query.limit);
|
|
66
|
+
return list;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async delete(userId: string, agentId?: EntityId): Promise<boolean> {
|
|
70
|
+
return this.profiles.delete(this.key(userId, agentId));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning: user profiles, memories that accumulate, knowledge that transfers.
|
|
3
|
+
* Supports always-on or agentic learning modes.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { EntityId } from '../core/types.js';
|
|
7
|
+
|
|
8
|
+
/** Learning mode: always persist/learn vs. only when agent explicitly stores */
|
|
9
|
+
export enum LearningMode {
|
|
10
|
+
/** Always: persist session, accumulate memories, update profiles automatically */
|
|
11
|
+
ALWAYS = 'always',
|
|
12
|
+
/** Agentic: agent decides when to store/update (e.g. via tools) */
|
|
13
|
+
AGENTIC = 'agentic',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** User profile that persists across sessions */
|
|
17
|
+
export interface UserProfile {
|
|
18
|
+
readonly id: EntityId;
|
|
19
|
+
readonly userId: string;
|
|
20
|
+
readonly agentId?: EntityId;
|
|
21
|
+
readonly displayName?: string;
|
|
22
|
+
readonly preferences?: Record<string, unknown>;
|
|
23
|
+
readonly metadata: Record<string, unknown>;
|
|
24
|
+
readonly createdAt: Date;
|
|
25
|
+
readonly updatedAt: Date;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Query for user profiles */
|
|
29
|
+
export interface UserProfileQuery {
|
|
30
|
+
readonly userId?: string;
|
|
31
|
+
readonly agentId?: EntityId;
|
|
32
|
+
readonly limit?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Store for user profiles (plug any DB) */
|
|
36
|
+
export interface UserProfileStore {
|
|
37
|
+
get(userId: string, agentId?: EntityId): Promise<UserProfile | null>;
|
|
38
|
+
set(profile: Omit<UserProfile, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserProfile>;
|
|
39
|
+
update(userId: string, updates: Partial<Omit<UserProfile, 'id' | 'userId' | 'createdAt'>>, agentId?: EntityId): Promise<UserProfile>;
|
|
40
|
+
list(query?: UserProfileQuery): Promise<UserProfile[]>;
|
|
41
|
+
delete(userId: string, agentId?: EntityId): Promise<boolean>;
|
|
42
|
+
}
|