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.
Files changed (114) hide show
  1. package/FEATURES.md +169 -0
  2. package/package.json +119 -0
  3. package/src/agent.ts +187 -0
  4. package/src/agentic/index.ts +87 -0
  5. package/src/agentic/runner.ts +386 -0
  6. package/src/agentic/types.ts +91 -0
  7. package/src/artifacts/artifact.ts +417 -0
  8. package/src/artifacts/index.ts +42 -0
  9. package/src/artifacts/media.ts +304 -0
  10. package/src/cli/index.ts +122 -0
  11. package/src/core/base-agent.ts +151 -0
  12. package/src/core/context-builder.ts +106 -0
  13. package/src/core/index.ts +8 -0
  14. package/src/core/schemas.ts +17 -0
  15. package/src/core/types.ts +158 -0
  16. package/src/create-agent.ts +309 -0
  17. package/src/debug-logger.ts +188 -0
  18. package/src/dx/agent.ts +88 -0
  19. package/src/dx/define-agent.ts +183 -0
  20. package/src/dx/dev-logger.ts +57 -0
  21. package/src/dx/index.ts +11 -0
  22. package/src/errors.ts +175 -0
  23. package/src/execution/engine.ts +522 -0
  24. package/src/execution/graph-builder.ts +362 -0
  25. package/src/execution/index.ts +8 -0
  26. package/src/execution/types.ts +257 -0
  27. package/src/execution/worker-pool.ts +308 -0
  28. package/src/extensions/index.ts +123 -0
  29. package/src/guardrails/allowlist.ts +155 -0
  30. package/src/guardrails/index.ts +17 -0
  31. package/src/guardrails/types.ts +159 -0
  32. package/src/guardrails/validator.ts +265 -0
  33. package/src/index.ts +74 -0
  34. package/src/knowledge/index.ts +5 -0
  35. package/src/knowledge/types.ts +52 -0
  36. package/src/learning/in-memory-store.ts +72 -0
  37. package/src/learning/index.ts +6 -0
  38. package/src/learning/types.ts +42 -0
  39. package/src/llm/cache.ts +300 -0
  40. package/src/llm/index.ts +22 -0
  41. package/src/llm/model-resolver.ts +81 -0
  42. package/src/llm/openai-provider.ts +313 -0
  43. package/src/llm/openrouter-provider.ts +29 -0
  44. package/src/llm/types.ts +131 -0
  45. package/src/memory/in-memory-store.ts +255 -0
  46. package/src/memory/index.ts +7 -0
  47. package/src/memory/types.ts +193 -0
  48. package/src/memory/vector-store.ts +251 -0
  49. package/src/observability/console-logger.ts +123 -0
  50. package/src/observability/index.ts +12 -0
  51. package/src/observability/metrics.ts +85 -0
  52. package/src/observability/otlp-exporter.ts +417 -0
  53. package/src/observability/tracer.ts +105 -0
  54. package/src/observability/types.ts +341 -0
  55. package/src/orchestration/agent-adapter.ts +33 -0
  56. package/src/orchestration/index.ts +34 -0
  57. package/src/orchestration/load-balancer.ts +151 -0
  58. package/src/orchestration/mcp-types.ts +59 -0
  59. package/src/orchestration/message-bus.ts +192 -0
  60. package/src/orchestration/orchestrator.ts +349 -0
  61. package/src/orchestration/pipeline.ts +66 -0
  62. package/src/orchestration/supervisor.ts +107 -0
  63. package/src/orchestration/swarm.ts +1099 -0
  64. package/src/orchestration/toolkit.ts +47 -0
  65. package/src/orchestration/types.ts +339 -0
  66. package/src/planner/classical-planner.ts +383 -0
  67. package/src/planner/index.ts +8 -0
  68. package/src/planner/llm-planner.ts +353 -0
  69. package/src/planner/types.ts +227 -0
  70. package/src/planner/validator.ts +297 -0
  71. package/src/production/circuit-breaker.ts +290 -0
  72. package/src/production/graceful-shutdown.ts +251 -0
  73. package/src/production/health.ts +333 -0
  74. package/src/production/index.ts +57 -0
  75. package/src/production/latency-eval.ts +62 -0
  76. package/src/production/rate-limiter.ts +287 -0
  77. package/src/production/resumable-stream.ts +289 -0
  78. package/src/production/types.ts +81 -0
  79. package/src/sdk/index.ts +374 -0
  80. package/src/session/db-driver.ts +50 -0
  81. package/src/session/in-memory-store.ts +235 -0
  82. package/src/session/index.ts +12 -0
  83. package/src/session/sql-store.ts +315 -0
  84. package/src/session/sqlite-store.ts +61 -0
  85. package/src/session/types.ts +153 -0
  86. package/src/tools/base-tool.ts +223 -0
  87. package/src/tools/browser-tool.ts +123 -0
  88. package/src/tools/calculator-tool.ts +265 -0
  89. package/src/tools/file-tools.ts +394 -0
  90. package/src/tools/github-tool.ts +432 -0
  91. package/src/tools/hackernews-tool.ts +187 -0
  92. package/src/tools/http-tool.ts +118 -0
  93. package/src/tools/index.ts +99 -0
  94. package/src/tools/jira-tool.ts +373 -0
  95. package/src/tools/notion-tool.ts +322 -0
  96. package/src/tools/openai-tool.ts +236 -0
  97. package/src/tools/registry.ts +131 -0
  98. package/src/tools/serpapi-tool.ts +234 -0
  99. package/src/tools/shell-tool.ts +118 -0
  100. package/src/tools/slack-tool.ts +327 -0
  101. package/src/tools/telegram-tool.ts +127 -0
  102. package/src/tools/types.ts +229 -0
  103. package/src/tools/websearch-tool.ts +335 -0
  104. package/src/tools/wikipedia-tool.ts +177 -0
  105. package/src/tools/yfinance-tool.ts +33 -0
  106. package/src/voice/index.ts +17 -0
  107. package/src/voice/voice-provider.ts +228 -0
  108. package/tests/artifact.test.ts +241 -0
  109. package/tests/circuit-breaker.test.ts +171 -0
  110. package/tests/health.test.ts +192 -0
  111. package/tests/llm-cache.test.ts +186 -0
  112. package/tests/rate-limiter.test.ts +161 -0
  113. package/tsconfig.json +29 -0
  114. package/vitest.config.ts +47 -0
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Core types and interfaces for the Agent Framework
3
+ */
4
+
5
+ import type { MemoryStore } from '../memory/types.js';
6
+ import type { ToolRegistry } from '../tools/types.js';
7
+ import type { Planner } from '../planner/types.js';
8
+
9
+ /**
10
+ * Unique identifier for agents, tasks, and other entities
11
+ */
12
+ export type EntityId = string;
13
+
14
+ /**
15
+ * Agent execution state
16
+ */
17
+ export enum AgentState {
18
+ IDLE = 'idle',
19
+ PLANNING = 'planning',
20
+ EXECUTING = 'executing',
21
+ PAUSED = 'paused',
22
+ COMPLETED = 'completed',
23
+ FAILED = 'failed',
24
+ CANCELLED = 'cancelled',
25
+ }
26
+
27
+ /**
28
+ * Context provided to agents during execution
29
+ */
30
+ export interface AgentContext {
31
+ readonly agentId: EntityId;
32
+ readonly memory: MemoryStore;
33
+ readonly tools: ToolRegistry;
34
+ readonly planner: Planner;
35
+ readonly metadata: Record<string, unknown>;
36
+ }
37
+
38
+ /**
39
+ * Configuration for creating an agent
40
+ */
41
+ export interface AgentConfig {
42
+ readonly id?: EntityId;
43
+ readonly name: string;
44
+ readonly description?: string;
45
+ readonly persona?: string;
46
+ readonly maxIterations?: number;
47
+ readonly timeoutMs?: number;
48
+ /** Enable debug logging for this agent */
49
+ readonly debug?: boolean;
50
+ }
51
+
52
+ /**
53
+ * Input to an agent execution
54
+ */
55
+ export interface AgentInput {
56
+ readonly prompt: string;
57
+ readonly context?: Record<string, unknown>;
58
+ readonly attachments?: Attachment[];
59
+ }
60
+
61
+ /**
62
+ * Output from an agent execution
63
+ */
64
+ export interface AgentOutput {
65
+ readonly result: unknown;
66
+ readonly state: AgentState;
67
+ readonly metadata: ExecutionMetadata;
68
+ }
69
+
70
+ /**
71
+ * Attachment for agent input/output
72
+ */
73
+ export interface Attachment {
74
+ readonly id: EntityId;
75
+ readonly type: string;
76
+ readonly content: unknown;
77
+ readonly metadata?: Record<string, unknown>;
78
+ }
79
+
80
+ /**
81
+ * Execution metadata
82
+ */
83
+ export interface ExecutionMetadata {
84
+ readonly startTime: Date;
85
+ readonly endTime?: Date;
86
+ readonly durationMs?: number;
87
+ readonly iterations: number;
88
+ readonly tokensUsed?: number;
89
+ readonly cost?: number;
90
+ }
91
+
92
+ /**
93
+ * Hook for agent lifecycle events
94
+ */
95
+ export interface AgentHooks {
96
+ beforeExecution?: (input: AgentInput, ctx: AgentContext) => Promise<void> | void;
97
+ afterExecution?: (output: AgentOutput, ctx: AgentContext) => Promise<void> | void;
98
+ onError?: (error: Error, ctx: AgentContext) => Promise<void> | void;
99
+ onStateChange?: (oldState: AgentState, newState: AgentState, ctx: AgentContext) => Promise<void> | void;
100
+ }
101
+
102
+ /**
103
+ * Abstract base class for all agents
104
+ */
105
+ export abstract class Agent {
106
+ readonly id: EntityId;
107
+ readonly name: string;
108
+ readonly description: string;
109
+ readonly persona?: string;
110
+ readonly config: AgentConfig;
111
+ protected state: AgentState = AgentState.IDLE;
112
+ protected hooks: AgentHooks = {};
113
+
114
+ constructor(config: AgentConfig) {
115
+ this.config = config;
116
+ this.id = config.id ?? generateId();
117
+ this.name = config.name;
118
+ this.description = config.description ?? '';
119
+ this.persona = config.persona;
120
+ }
121
+
122
+ /**
123
+ * Execute the agent with the given input and context
124
+ */
125
+ abstract run(input: AgentInput, ctx: AgentContext): Promise<AgentOutput>;
126
+
127
+ /**
128
+ * Get current agent state
129
+ */
130
+ getState(): AgentState {
131
+ return this.state;
132
+ }
133
+
134
+ /**
135
+ * Set lifecycle hooks
136
+ */
137
+ setHooks(hooks: AgentHooks): void {
138
+ this.hooks = hooks;
139
+ }
140
+
141
+ /**
142
+ * Update agent state with hook notification
143
+ */
144
+ protected async setState(newState: AgentState, ctx: AgentContext): Promise<void> {
145
+ const oldState = this.state;
146
+ this.state = newState;
147
+ if (this.hooks.onStateChange) {
148
+ await this.hooks.onStateChange(oldState, newState, ctx);
149
+ }
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Generate a unique identifier
155
+ */
156
+ function generateId(): EntityId {
157
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
158
+ }
@@ -0,0 +1,309 @@
1
+ /**
2
+ * One-line production-grade agent creation.
3
+ *
4
+ * Auto-configures: LLM (from env), memory/session, default tools, optional guardrails.
5
+ * Use createAgent({ name, instructions }) for minimal setup; override any part as needed.
6
+ */
7
+
8
+ import type { LLMProvider } from './llm/types.js';
9
+ import type { Message } from './llm/types.js';
10
+ import type { Tool, ToolRegistry, ToolMiddleware } from './tools/types.js';
11
+ import type { SessionStore } from './session/types.js';
12
+ import type { GuardrailEngine } from './guardrails/types.js';
13
+ import type { UserProfileStore } from './learning/types.js';
14
+ import type { LearningMode } from './learning/types.js';
15
+ import type { MemoryStore } from './memory/types.js';
16
+ import type { RAGEngine } from './knowledge/types.js';
17
+ import type { z } from 'zod';
18
+ import type { AgenticStreamHooks } from './agentic/types.js';
19
+ import type { AgenticRunResult } from './agentic/types.js';
20
+ import type { Logger } from './observability/types.js';
21
+ import { createAgenticAgent } from './agentic/index.js';
22
+ import { OpenAIProvider, resolveModelString, isModelString } from './llm/index.js';
23
+ import { HttpClientTool } from './tools/http-tool.js';
24
+ import { BrowserTool } from './tools/browser-tool.js';
25
+ import { InMemorySessionStore } from './session/index.js';
26
+ import { GuardrailValidator, createSensitiveDataRule } from './guardrails/index.js';
27
+ import { SessionState } from './session/types.js';
28
+ import { ConfigError } from './errors.js';
29
+ import { toToolRegistry, type ToolProvider } from './tools/registry.js';
30
+ import { createDevLogger } from './dx/dev-logger.js';
31
+ import { createDevToolMiddleware } from './dx/dev-logger.js';
32
+
33
+ /** Environment variable names for auto LLM config */
34
+ const ENV_API_KEY = 'OPENAI_API_KEY';
35
+ const ENV_MODEL = 'OPENAI_MODEL';
36
+ const ENV_BASE_URL = 'OPENAI_BASE_URL';
37
+ const ENV_OPENROUTER_API_KEY = 'OPENROUTER_API_KEY';
38
+ const ENV_OPENROUTER_MODEL = 'OPENROUTER_MODEL';
39
+ const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';
40
+
41
+ export interface CreateAgentOptions {
42
+ /** Agent name */
43
+ name: string;
44
+ /** System instructions / prompt */
45
+ instructions: string;
46
+ /** LLM provider. If omitted, uses OpenAI from OPENAI_API_KEY (and optional OPENAI_MODEL). */
47
+ llm?: LLMProvider;
48
+ /**
49
+ * Model: either a plain model id (e.g. gpt-4o) or Agno-style "provider:model_id".
50
+ * Examples: "openai:gpt-4o", "openrouter:anthropic/claude-3.5-sonnet", "ollama:llama3.2".
51
+ * Ignored if llm is provided.
52
+ */
53
+ model?: string;
54
+ /** API key when using auto OpenAI. Falls back to OPENAI_API_KEY. Optional when baseURL is a local server (e.g. Ollama). */
55
+ apiKey?: string;
56
+ /** Base URL for the API (e.g. http://localhost:11434/v1 for Ollama). Falls back to OPENAI_BASE_URL. */
57
+ baseURL?: string;
58
+ /** Use OpenRouter (many models via one API). Set OPENROUTER_API_KEY or pass apiKey/model here. */
59
+ openRouter?: { apiKey?: string; model?: string };
60
+ /** Tools: array or registry. Default: [HttpClientTool(), BrowserTool()]. */
61
+ tools?: Tool[] | ToolRegistry;
62
+ /** Cross-tool middleware (logging, rate limit, etc.). */
63
+ toolMiddleware?: ToolMiddleware[];
64
+ /** Session store for conversation persistence. Default: InMemorySessionStore(). Plug any DB by implementing SessionStore. */
65
+ sessionStore?: SessionStore;
66
+ /** Guardrails. Default: GuardrailValidator with sensitive-data rule. Set false to disable. */
67
+ guardrails?: GuardrailEngine | false;
68
+ /** Max agentic steps (default: 10) */
69
+ maxSteps?: number;
70
+ /** Run timeout ms (default: 60000) */
71
+ timeoutMs?: number;
72
+ /** Retry policy for LLM/tool calls */
73
+ retry?: { maxRetries?: number; backoffMs?: number; maxBackoffMs?: number };
74
+ /** Optional logger for production observability */
75
+ logger?: Logger;
76
+ /** Learning: always persist/learn vs agentic (default: always when sessionStore used) */
77
+ learningMode?: LearningMode;
78
+ /** User profiles that persist across sessions (plug any DB) */
79
+ userProfileStore?: UserProfileStore;
80
+ /** Long-term memory / knowledge store (for RAG, memories that accumulate) */
81
+ memoryStore?: MemoryStore;
82
+ /** RAG engine: agentic RAG, hybrid search, reranking (optional) */
83
+ ragEngine?: RAGEngine;
84
+ /** Type-safe input: Zod schema for run input (optional) */
85
+ inputSchema?: z.ZodType;
86
+ /** Type-safe output: Zod schema for run output (optional) */
87
+ outputSchema?: z.ZodType;
88
+ /** Dev mode: auto-attach console logger + tool call logging (best DX) */
89
+ dev?: boolean;
90
+ }
91
+
92
+ export interface AgentRunOptions {
93
+ /** Optional session ID to load/save conversation. If provided, messages are persisted. */
94
+ sessionId?: string;
95
+ /** Optional user ID for session metadata */
96
+ userId?: string;
97
+ /** Stream / progress hooks */
98
+ onChunk?: (text: string) => void;
99
+ onToolCall?: (name: string, args: Record<string, unknown>) => void;
100
+ onToolResult?: (name: string, result: unknown) => void;
101
+ onStep?: (step: number) => void;
102
+ }
103
+
104
+ export interface CreateAgentResult {
105
+ name: string;
106
+ instructions: string;
107
+ /** Run the agent with a prompt. Use sessionId in options for conversation persistence. */
108
+ run(prompt: string, options?: AgentRunOptions): Promise<AgenticRunResult>;
109
+ /** Create a new session for this agent (returns sessionId to pass to run). */
110
+ createSession(userId?: string): Promise<string>;
111
+ /** Get messages for a session (if using sessionStore). */
112
+ getSessionMessages(sessionId: string): Promise<Message[]>;
113
+ }
114
+
115
+ /**
116
+ * Create a production-grade agent with one line.
117
+ * Auto-configures LLM (OpenAI from env), default tools (HTTP), session store, and optional guardrails.
118
+ *
119
+ * @example
120
+ * // Minimal: uses OPENAI_API_KEY, default tools and session
121
+ * const agent = createAgent({ name: 'Assistant', instructions: 'You are helpful.' });
122
+ * const result = await agent.run('Hello!');
123
+ *
124
+ * @example
125
+ * // With session for conversation memory
126
+ * const agent = createAgent({ name: 'Assistant', instructions: 'You are helpful.' });
127
+ * const sessionId = await agent.createSession('user-1');
128
+ * const result = await agent.run('What did I just say?', { sessionId });
129
+ *
130
+ * @example
131
+ * // Override model or provide your own LLM
132
+ * const agent = createAgent({
133
+ * name: 'Assistant',
134
+ * instructions: 'You are helpful.',
135
+ * model: 'gpt-4o-mini',
136
+ * apiKey: process.env.MY_KEY,
137
+ * });
138
+ *
139
+ * @example
140
+ * // Llama/Bern or any OpenAI-compatible endpoint (e.g. Ollama)
141
+ * const agent = createAgent({
142
+ * name: 'Assistant',
143
+ * instructions: 'You are helpful.',
144
+ * baseURL: 'http://localhost:11434/v1',
145
+ * model: 'llama3.2',
146
+ * });
147
+ *
148
+ * @example
149
+ * // Agno-style model string: provider:model_id (openai, openrouter, ollama)
150
+ * const agent = createAgent({
151
+ * name: 'Assistant',
152
+ * instructions: 'You are helpful.',
153
+ * model: 'openrouter:anthropic/claude-3.5-sonnet',
154
+ * });
155
+ */
156
+ export function createAgent(options: CreateAgentOptions): CreateAgentResult {
157
+ const {
158
+ name,
159
+ instructions,
160
+ llm: providedLlm,
161
+ model = typeof process !== 'undefined' && process.env?.[ENV_MODEL] ? process.env[ENV_MODEL] : 'gpt-4o',
162
+ apiKey = typeof process !== 'undefined' && process.env?.[ENV_API_KEY] ? process.env[ENV_API_KEY] : undefined,
163
+ baseURL = (typeof process !== 'undefined' && process.env?.[ENV_BASE_URL]) ? process.env[ENV_BASE_URL] : undefined,
164
+ tools: toolsOption = [new HttpClientTool(), new BrowserTool()],
165
+ toolMiddleware,
166
+ sessionStore = new InMemorySessionStore(),
167
+ guardrails: guardrailsOption = true,
168
+ maxSteps = 10,
169
+ timeoutMs = 60_000,
170
+ retry,
171
+ logger,
172
+ dev,
173
+ } = options;
174
+
175
+ if (!name || typeof name !== 'string' || name.trim() === '') {
176
+ throw new ConfigError('createAgent: name is required and must be a non-empty string', { context: { options: { name } } });
177
+ }
178
+ if (!instructions || typeof instructions !== 'string' || instructions.trim() === '') {
179
+ throw new ConfigError('createAgent: instructions is required and must be a non-empty string', { context: { options: { name } } });
180
+ }
181
+
182
+ const tools = toToolRegistry(toolsOption as ToolProvider);
183
+
184
+ const getEnv = typeof process !== 'undefined' ? (k: string) => process.env?.[k] : undefined;
185
+ let llm: LLMProvider;
186
+ if (providedLlm) {
187
+ llm = providedLlm;
188
+ } else if (model && isModelString(model)) {
189
+ const resolved = resolveModelString(model, getEnv);
190
+ if (!resolved) {
191
+ throw new Error(`createAgent: Unknown provider in model string "${model}". Use openai:, openrouter:, or ollama:.`);
192
+ }
193
+ if (!resolved.apiKey) {
194
+ throw new Error(
195
+ `createAgent: Model "${model}" requires an API key. Set OPENAI_API_KEY or OPENROUTER_API_KEY (Ollama needs no key).`
196
+ );
197
+ }
198
+ llm = new OpenAIProvider({
199
+ apiKey: resolved.apiKey,
200
+ baseURL: resolved.baseURL,
201
+ model: resolved.model,
202
+ });
203
+ } else {
204
+ const openRouterKey =
205
+ options.openRouter?.apiKey ?? getEnv?.(ENV_OPENROUTER_API_KEY);
206
+ if (openRouterKey) {
207
+ const openRouterModel =
208
+ options.openRouter?.model ?? getEnv?.(ENV_OPENROUTER_MODEL) ?? model;
209
+ llm = new OpenAIProvider({
210
+ apiKey: openRouterKey,
211
+ baseURL: OPENROUTER_BASE_URL,
212
+ model: (openRouterModel as string) || 'openai/gpt-4o',
213
+ });
214
+ } else if (apiKey || baseURL) {
215
+ llm = new OpenAIProvider({ apiKey, baseURL, model: model as string });
216
+ } else {
217
+ throw new Error(
218
+ `createAgent: No LLM provided. Set ${ENV_API_KEY}, or ${ENV_OPENROUTER_API_KEY}, or ${ENV_BASE_URL}, or pass model "provider:model_id", { llm }, { apiKey }, or { baseURL }.`
219
+ );
220
+ }
221
+ }
222
+
223
+ const guardrails: GuardrailEngine | undefined =
224
+ guardrailsOption === false
225
+ ? undefined
226
+ : guardrailsOption === true
227
+ ? (() => {
228
+ const engine = new GuardrailValidator({ rules: [createSensitiveDataRule()] });
229
+ return engine;
230
+ })()
231
+ : guardrailsOption;
232
+
233
+ const effectiveLogger = logger ?? (dev ? createDevLogger() : undefined);
234
+ const effectiveToolMiddleware = [
235
+ ...(toolMiddleware ?? []),
236
+ ...(dev ? [createDevToolMiddleware()] : []),
237
+ ];
238
+
239
+ if (effectiveLogger?.debug) {
240
+ effectiveLogger.debug('createAgent: initializing', { agentId: name }, { toolsCount: tools.list().length });
241
+ }
242
+
243
+ const agent = createAgenticAgent({
244
+ name,
245
+ instructions,
246
+ llm,
247
+ tools: tools,
248
+ toolMiddleware: effectiveToolMiddleware.length ? effectiveToolMiddleware : undefined,
249
+ maxSteps,
250
+ timeoutMs,
251
+ retry,
252
+ guardrails,
253
+ });
254
+
255
+ return {
256
+ name,
257
+ instructions,
258
+ async run(prompt: string, runOptions?: AgentRunOptions): Promise<AgenticRunResult> {
259
+ const sessionId = runOptions?.sessionId;
260
+ const hooks: AgenticStreamHooks = {
261
+ onChunk: runOptions?.onChunk,
262
+ onToolCall: runOptions?.onToolCall,
263
+ onToolResult: runOptions?.onToolResult,
264
+ onStep: runOptions?.onStep,
265
+ };
266
+
267
+ let messages: Message[] | undefined;
268
+ if (sessionId) {
269
+ const session = await sessionStore.get(sessionId);
270
+ const history = session?.messages ?? [];
271
+ messages = [...history, { role: 'user', content: prompt }];
272
+ }
273
+
274
+ const result = await agent.run(
275
+ {
276
+ prompt: messages ? '' : prompt,
277
+ instructions,
278
+ messages,
279
+ maxSteps,
280
+ timeoutMs,
281
+ },
282
+ hooks
283
+ );
284
+
285
+ if (sessionId && result.messages?.length) {
286
+ await sessionStore.update(sessionId, {
287
+ messages: result.messages,
288
+ state: SessionState.ACTIVE,
289
+ });
290
+ }
291
+
292
+ return result;
293
+ },
294
+ async createSession(userId?: string): Promise<string> {
295
+ const session = await sessionStore.create({
296
+ agentId: name,
297
+ userId,
298
+ state: SessionState.ACTIVE,
299
+ messages: [],
300
+ metadata: {},
301
+ context: {},
302
+ });
303
+ return session.id;
304
+ },
305
+ async getSessionMessages(sessionId: string): Promise<Message[]> {
306
+ return sessionStore.getMessages(sessionId);
307
+ },
308
+ };
309
+ }
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Centralized debug logger for the agent framework
3
+ *
4
+ * Provides comprehensive debug logging across all components with
5
+ * configurable debug mode support.
6
+ */
7
+
8
+ import type { Logger, LogContext } from './observability/types.js';
9
+
10
+ /**
11
+ * Debug logger configuration
12
+ */
13
+ export interface DebugLoggerConfig {
14
+ /** Enable debug logging */
15
+ enabled: boolean;
16
+ /** Component name prefix */
17
+ component: string;
18
+ /** Parent logger for nested contexts */
19
+ parent?: DebugLogger;
20
+ /** Additional context to include in all logs */
21
+ context?: Partial<LogContext>;
22
+ }
23
+
24
+ /**
25
+ * Format metadata for output
26
+ */
27
+ function formatMetadata(metadata?: Record<string, unknown>): string {
28
+ if (!metadata || Object.keys(metadata).length === 0) return '';
29
+ try {
30
+ return JSON.stringify(metadata);
31
+ } catch {
32
+ return '[metadata serialization failed]';
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Centralized debug logger that respects debug mode settings
38
+ */
39
+ export class DebugLogger implements Logger {
40
+ private config: DebugLoggerConfig;
41
+ private prefix: string;
42
+
43
+ constructor(config: DebugLoggerConfig) {
44
+ this.config = config;
45
+ this.prefix = `[${config.component}]`;
46
+ }
47
+
48
+ /**
49
+ * Check if debug logging is enabled
50
+ */
51
+ isEnabled(): boolean {
52
+ return this.config.enabled;
53
+ }
54
+
55
+ /**
56
+ * Log a debug message (only if debug is enabled)
57
+ */
58
+ debug(message: string, _context?: Partial<LogContext>, metadata?: Record<string, unknown>): void {
59
+ if (!this.config.enabled) return;
60
+ console.debug(`${this.prefix} ${message}`, formatMetadata(metadata));
61
+ }
62
+
63
+ /**
64
+ * Log an info message
65
+ */
66
+ info(message: string, _context?: Partial<LogContext>, metadata?: Record<string, unknown>): void {
67
+ console.info(`${this.prefix} ${message}`, formatMetadata(metadata));
68
+ }
69
+
70
+ /**
71
+ * Log a warning message
72
+ */
73
+ warn(message: string, _context?: Partial<LogContext>, metadata?: Record<string, unknown>): void {
74
+ console.warn(`${this.prefix} ⚠️ ${message}`, formatMetadata(metadata));
75
+ }
76
+
77
+ /**
78
+ * Log an error message
79
+ */
80
+ error(message: string, _context?: Partial<LogContext>, metadata?: Record<string, unknown>): void {
81
+ console.error(`${this.prefix} ❌ ${message}`, formatMetadata(metadata));
82
+ }
83
+
84
+ /**
85
+ * Log a fatal message
86
+ */
87
+ fatal(message: string, _context?: Partial<LogContext>, metadata?: Record<string, unknown>): void {
88
+ console.error(`${this.prefix} 💀 [FATAL] ${message}`, formatMetadata(metadata));
89
+ }
90
+
91
+ /**
92
+ * Create a child logger with additional context
93
+ */
94
+ child(additionalContext: Partial<LogContext>): DebugLogger {
95
+ return new DebugLogger({
96
+ enabled: this.config.enabled,
97
+ component: this.config.component,
98
+ parent: this,
99
+ context: { ...this.config.context, ...additionalContext },
100
+ });
101
+ }
102
+
103
+ /**
104
+ * Log the start of an operation
105
+ */
106
+ logStart(operation: string, metadata?: Record<string, unknown>): void {
107
+ if (!this.config.enabled) return;
108
+ console.debug(`${this.prefix} ▶️ Starting: ${operation}`, formatMetadata(metadata));
109
+ }
110
+
111
+ /**
112
+ * Log the completion of an operation
113
+ */
114
+ logComplete(operation: string, durationMs?: number, metadata?: Record<string, unknown>): void {
115
+ if (!this.config.enabled) return;
116
+ const duration = durationMs !== undefined ? ` (${durationMs}ms)` : '';
117
+ console.debug(`${this.prefix} ✅ Completed: ${operation}${duration}`, formatMetadata(metadata));
118
+ }
119
+
120
+ /**
121
+ * Log a step in a multi-step process
122
+ */
123
+ logStep(step: string, current: number, total: number, metadata?: Record<string, unknown>): void {
124
+ if (!this.config.enabled) return;
125
+ console.debug(`${this.prefix} 📍 Step ${current}/${total}: ${step}`, formatMetadata(metadata));
126
+ }
127
+
128
+ /**
129
+ * Log state changes
130
+ */
131
+ logStateChange(entity: string, from: string, to: string, metadata?: Record<string, unknown>): void {
132
+ if (!this.config.enabled) return;
133
+ console.debug(`${this.prefix} 🔄 ${entity} state: ${from} → ${to}`, formatMetadata(metadata));
134
+ }
135
+
136
+ /**
137
+ * Log data for debugging
138
+ */
139
+ logData(label: string, data: unknown): void {
140
+ if (!this.config.enabled) return;
141
+ const preview = typeof data === 'string' ? data : JSON.stringify(data);
142
+ const truncated = preview.length > 200 ? preview.slice(0, 200) + '...' : preview;
143
+ console.debug(`${this.prefix} 📊 ${label}: ${truncated}`);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Global debug configuration
149
+ */
150
+ let globalDebugEnabled = false;
151
+
152
+ /**
153
+ * Enable or disable global debug mode
154
+ */
155
+ export function setGlobalDebug(enabled: boolean): void {
156
+ globalDebugEnabled = enabled;
157
+ }
158
+
159
+ /**
160
+ * Check if global debug mode is enabled
161
+ */
162
+ export function isGlobalDebugEnabled(): boolean {
163
+ return globalDebugEnabled;
164
+ }
165
+
166
+ /**
167
+ * Create a debug logger for a component
168
+ */
169
+ export function createDebugLogger(component: string, enabled?: boolean): DebugLogger {
170
+ return new DebugLogger({
171
+ enabled: enabled ?? globalDebugEnabled,
172
+ component,
173
+ });
174
+ }
175
+
176
+ /**
177
+ * Create a no-op logger for when debugging is disabled
178
+ */
179
+ export function createNoopLogger(): Logger {
180
+ return {
181
+ debug: () => { },
182
+ info: () => { },
183
+ warn: () => { },
184
+ error: () => { },
185
+ fatal: () => { },
186
+ child: () => createNoopLogger(),
187
+ };
188
+ }