@stevederico/dotbot 0.16.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/CHANGELOG.md +136 -0
- package/README.md +380 -0
- package/bin/dotbot.js +461 -0
- package/core/agent.js +779 -0
- package/core/compaction.js +261 -0
- package/core/cron_handler.js +262 -0
- package/core/events.js +229 -0
- package/core/failover.js +193 -0
- package/core/gptoss_tool_parser.js +173 -0
- package/core/init.js +154 -0
- package/core/normalize.js +324 -0
- package/core/trigger_handler.js +148 -0
- package/docs/core.md +103 -0
- package/docs/protected-files.md +59 -0
- package/examples/sqlite-session-example.js +69 -0
- package/index.js +341 -0
- package/observer/index.js +164 -0
- package/package.json +42 -0
- package/storage/CronStore.js +145 -0
- package/storage/EventStore.js +71 -0
- package/storage/MemoryStore.js +175 -0
- package/storage/MongoAdapter.js +291 -0
- package/storage/MongoCronAdapter.js +347 -0
- package/storage/MongoTaskAdapter.js +242 -0
- package/storage/MongoTriggerAdapter.js +158 -0
- package/storage/SQLiteAdapter.js +382 -0
- package/storage/SQLiteCronAdapter.js +562 -0
- package/storage/SQLiteEventStore.js +300 -0
- package/storage/SQLiteMemoryAdapter.js +240 -0
- package/storage/SQLiteTaskAdapter.js +419 -0
- package/storage/SQLiteTriggerAdapter.js +262 -0
- package/storage/SessionStore.js +149 -0
- package/storage/TaskStore.js +100 -0
- package/storage/TriggerStore.js +90 -0
- package/storage/cron_constants.js +48 -0
- package/storage/index.js +21 -0
- package/tools/appgen.js +311 -0
- package/tools/browser.js +634 -0
- package/tools/code.js +101 -0
- package/tools/events.js +145 -0
- package/tools/files.js +201 -0
- package/tools/images.js +253 -0
- package/tools/index.js +97 -0
- package/tools/jobs.js +159 -0
- package/tools/memory.js +332 -0
- package/tools/messages.js +135 -0
- package/tools/notify.js +42 -0
- package/tools/tasks.js +404 -0
- package/tools/triggers.js +159 -0
- package/tools/weather.js +82 -0
- package/tools/web.js +283 -0
- package/utils/providers.js +136 -0
package/docs/core.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Core AI Agent Framework Features (Both Have)
|
|
2
|
+
|
|
3
|
+
1. Multi-Provider AI Support - Anthropic, OpenAI, multiple LLM backends
|
|
4
|
+
2. Long-Term Memory - Persistent storage across sessions
|
|
5
|
+
3. Tool Execution System - Agent can perform actions (web search, file ops, etc.)
|
|
6
|
+
4. Session Management - Track conversation history
|
|
7
|
+
5. Scheduled Tasks - Cron/recurring actions
|
|
8
|
+
6. Web Search Integration - Access current information
|
|
9
|
+
7. File Operations - Read/write/manage files
|
|
10
|
+
8. Context Preservation - Maintain state between turns
|
|
11
|
+
|
|
12
|
+
The "Must-Have" List
|
|
13
|
+
|
|
14
|
+
Every AI agent framework needs:
|
|
15
|
+
|
|
16
|
+
- ✅ LLM Integration (API to Claude/GPT/etc.)
|
|
17
|
+
- ✅ Memory/Storage (remember past conversations)
|
|
18
|
+
- ✅ Tool System (execute actions beyond chat)
|
|
19
|
+
- ✅ Session Tracking (multi-turn conversations)
|
|
20
|
+
- ✅ Scheduling (delayed/recurring tasks)
|
|
21
|
+
|
|
22
|
+
Optional but common:
|
|
23
|
+
- Web search
|
|
24
|
+
- File management
|
|
25
|
+
- Multi-user support
|
|
26
|
+
- Event triggers
|
|
27
|
+
Standard AI Agent Tools (Industry Common)
|
|
28
|
+
|
|
29
|
+
Core Tier (Nearly Universal)
|
|
30
|
+
|
|
31
|
+
1. Memory/Storage - Save, search, retrieve information
|
|
32
|
+
2. Web Search - Current information lookup
|
|
33
|
+
3. Web Fetch - HTTP requests to APIs/URLs
|
|
34
|
+
4. File Operations - Read, write, list, delete files
|
|
35
|
+
5. Code Execution - Run code snippets (Python/JS/etc.)
|
|
36
|
+
|
|
37
|
+
Common Tier (Most Frameworks)
|
|
38
|
+
|
|
39
|
+
6. Calculator/Math - Precise calculations
|
|
40
|
+
7. Time/Date - Current time, scheduling
|
|
41
|
+
8. Command Execution - Shell commands (sandboxed)
|
|
42
|
+
9. Database Queries - Read/write to databases
|
|
43
|
+
|
|
44
|
+
Extended Tier (Advanced Frameworks)
|
|
45
|
+
|
|
46
|
+
10. Browser Automation - Navigate, click, screenshot
|
|
47
|
+
11. Image Generation - Create images from prompts
|
|
48
|
+
12. Image Analysis - Describe/analyze images
|
|
49
|
+
13. Email - Send/read emails
|
|
50
|
+
14. Notifications - Push alerts to users
|
|
51
|
+
15. Weather - Current conditions/forecasts
|
|
52
|
+
|
|
53
|
+
Your Library (@dottie/agent) Has:
|
|
54
|
+
|
|
55
|
+
✅ Memory (6 tools)
|
|
56
|
+
✅ Web (3 tools)
|
|
57
|
+
✅ Files (6 tools)
|
|
58
|
+
✅ Code execution (1 tool)
|
|
59
|
+
✅ Browser (7 tools)
|
|
60
|
+
✅ Images (3 tools)
|
|
61
|
+
✅ Weather (1 tool)
|
|
62
|
+
✅ Notifications (1 tool)
|
|
63
|
+
✅ Messages (4 tools)
|
|
64
|
+
✅ Goals (9 tools)
|
|
65
|
+
✅ Triggers (4 tools)
|
|
66
|
+
|
|
67
|
+
45 total - well above baseline expectations.
|
|
68
|
+
|
|
69
|
+
Missing Common Tools (Consider Adding)
|
|
70
|
+
|
|
71
|
+
- Calculator - Math operations (LLMs are bad at precise math)
|
|
72
|
+
- Time/Date - Current time, timezone conversions
|
|
73
|
+
- Email - Send/read emails
|
|
74
|
+
- Database - Direct SQL/NoSQL queries
|
|
75
|
+
|
|
76
|
+
Minimal Viable Agent Toolkit
|
|
77
|
+
|
|
78
|
+
If starting from scratch, the absolute minimum:
|
|
79
|
+
|
|
80
|
+
1. Memory (save/search)
|
|
81
|
+
2. Web search
|
|
82
|
+
3. File read/write
|
|
83
|
+
4. Code execution
|
|
84
|
+
|
|
85
|
+
Everything else is optional depending on use case.
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
Anthropic SDK
|
|
89
|
+
Built-in tools - Read files, run bash commands, edit code, search web, glob patterns. Zero setup needed.
|
|
90
|
+
Context management - Automatic compaction, long-running sessions, context windows handled for you.
|
|
91
|
+
Agent loop - Built-in gather → action → verify → repeat pattern.
|
|
92
|
+
MCP integration - Connect to any MCP server for enterprise tools (Slack, GitHub, Drive, etc).
|
|
93
|
+
Hooks - Intercept tool calls, modify behavior, add custom logic.
|
|
94
|
+
Subagents - Spawn specialized agents for parallel work.
|
|
95
|
+
Permissions - Fine-grained control over what agents can access/modify.
|
|
96
|
+
Structured outputs - JSON schema support.
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
xAI
|
|
100
|
+
|
|
101
|
+
xai-sdk (Python/TypeScript) - standard client SDK
|
|
102
|
+
Agent Tools API - server-side tools (web search, X search, code execution, MCP, file search)
|
|
103
|
+
Agentic tool calling - Grok decides when to invoke tools autonomously
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Absolutely! Yes, you should definitely protect .ssh and similar system-level directories. Here's a critical list of system paths to exclude:
|
|
2
|
+
|
|
3
|
+
Critical System Directories (NEVER SHARE)
|
|
4
|
+
|
|
5
|
+
~/.ssh/ # SSH keys, known_hosts, config
|
|
6
|
+
~/.aws/ # AWS credentials
|
|
7
|
+
~/.config/ # App configs (may contain tokens)
|
|
8
|
+
~/.kube/ # Kubernetes credentials
|
|
9
|
+
~/.docker/ # Docker credentials
|
|
10
|
+
~/.gnupg/ # GPG keys
|
|
11
|
+
~/.password-store/ # Password manager data
|
|
12
|
+
~/Library/Keychains/ # macOS keychain files
|
|
13
|
+
~/Library/Application Support/*/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Shell & Environment
|
|
17
|
+
|
|
18
|
+
~/.zshrc # May contain exported secrets
|
|
19
|
+
~/.bashrc
|
|
20
|
+
~/.bash_profile
|
|
21
|
+
~/.zsh_history # Command history (may leak secrets)
|
|
22
|
+
~/.bash_history
|
|
23
|
+
~/.netrc # Network credentials
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
API & Service Credentials
|
|
27
|
+
|
|
28
|
+
~/.gitconfig # May contain GitHub tokens
|
|
29
|
+
~/.npmrc # NPM tokens
|
|
30
|
+
~/.pypirc # PyPI credentials
|
|
31
|
+
~/.gem/credentials # RubyGems API keys
|
|
32
|
+
~/.gradle/gradle.properties
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
Cloud & Infrastructure
|
|
36
|
+
|
|
37
|
+
~/.azure/
|
|
38
|
+
~/.gcloud/
|
|
39
|
+
~/.terraform.d/
|
|
40
|
+
~/.ansible/
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
Browser & Personal Data
|
|
44
|
+
|
|
45
|
+
~/Library/Safari/
|
|
46
|
+
~/Library/Cookies/
|
|
47
|
+
~/Library/Application Support/Google/Chrome/
|
|
48
|
+
~/Library/Application Support/Firefox/
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
Dottie-Specific (Your App)
|
|
52
|
+
|
|
53
|
+
~/.dottie/logs/ # May contain user conversations
|
|
54
|
+
~/.dottie/chat_history.json
|
|
55
|
+
~/.dottie/*.db
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
Bottom line: Any path under ~ (home directory) that contains credentials, personal data, command history, or configuration files should be protected. The general rule is: never search/glob/grep from ~ or /Users/sd root — only within specific project directories.
|
|
59
|
+
ctrl+q to copy · 6 snippets
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLiteSessionStore Usage Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates how to use SQLite as a session storage backend
|
|
5
|
+
* for the @dottie/agent library. Requires Node.js 22.5+.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createAgent, SQLiteSessionStore, coreTools } from '@dottie/agent';
|
|
9
|
+
|
|
10
|
+
// Initialize SQLite session store
|
|
11
|
+
const sessionStore = new SQLiteSessionStore();
|
|
12
|
+
await sessionStore.init('./sessions.db', {
|
|
13
|
+
// Optional: Fetch user preferences from your database
|
|
14
|
+
prefsFetcher: async (userId) => {
|
|
15
|
+
// Example: fetch from a user database
|
|
16
|
+
return {
|
|
17
|
+
agentName: 'Dottie',
|
|
18
|
+
agentPersonality: 'helpful and concise',
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
// Optional: Ensure user heartbeat for cron tasks
|
|
22
|
+
heartbeatEnsurer: async (userId) => {
|
|
23
|
+
// Example: update last_seen timestamp in user database
|
|
24
|
+
console.log(`User ${userId} active`);
|
|
25
|
+
return null;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Create agent with SQLite session storage
|
|
30
|
+
const agent = createAgent({
|
|
31
|
+
sessionStore,
|
|
32
|
+
providers: {
|
|
33
|
+
anthropic: { apiKey: process.env.ANTHROPIC_API_KEY },
|
|
34
|
+
},
|
|
35
|
+
tools: coreTools,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Example 1: Create a new session
|
|
39
|
+
const session = await agent.createSession('user-123', 'claude-sonnet-4-5', 'anthropic');
|
|
40
|
+
console.log('Created session:', session.id);
|
|
41
|
+
|
|
42
|
+
// Example 2: Chat with the agent
|
|
43
|
+
for await (const event of agent.chat({
|
|
44
|
+
sessionId: session.id,
|
|
45
|
+
message: 'What can you help me with?',
|
|
46
|
+
provider: 'anthropic',
|
|
47
|
+
model: 'claude-sonnet-4-5',
|
|
48
|
+
})) {
|
|
49
|
+
if (event.type === 'content_block_delta' && event.delta?.type === 'text_delta') {
|
|
50
|
+
process.stdout.write(event.delta.text);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
console.log('\n');
|
|
54
|
+
|
|
55
|
+
// Example 3: List all sessions for a user
|
|
56
|
+
const sessions = await sessionStore.listSessions('user-123');
|
|
57
|
+
console.log('User sessions:', sessions);
|
|
58
|
+
|
|
59
|
+
// Example 4: Get or create default session
|
|
60
|
+
const defaultSession = await sessionStore.getOrCreateDefaultSession('user-123');
|
|
61
|
+
console.log('Default session:', defaultSession.id);
|
|
62
|
+
|
|
63
|
+
// Example 5: Clear session history
|
|
64
|
+
await sessionStore.clearSession(session.id);
|
|
65
|
+
console.log('Session cleared');
|
|
66
|
+
|
|
67
|
+
// Example 6: Delete a session
|
|
68
|
+
await sessionStore.deleteSession(session.id, 'user-123');
|
|
69
|
+
console.log('Session deleted');
|
package/index.js
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DotBot Agent Library
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic AI agent system with tool execution, session management,
|
|
5
|
+
* and scheduled tasks.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Import tool arrays for use in createAgent()
|
|
9
|
+
import {
|
|
10
|
+
coreTools,
|
|
11
|
+
memoryTools,
|
|
12
|
+
webTools,
|
|
13
|
+
codeTools,
|
|
14
|
+
fileTools,
|
|
15
|
+
messageTools,
|
|
16
|
+
imageTools,
|
|
17
|
+
weatherTools,
|
|
18
|
+
notifyTools,
|
|
19
|
+
createBrowserTools,
|
|
20
|
+
taskTools,
|
|
21
|
+
goalTools,
|
|
22
|
+
triggerTools,
|
|
23
|
+
jobTools,
|
|
24
|
+
cronTools,
|
|
25
|
+
eventTools,
|
|
26
|
+
appgenTools,
|
|
27
|
+
} from './tools/index.js';
|
|
28
|
+
|
|
29
|
+
// Export core abstractions
|
|
30
|
+
export {
|
|
31
|
+
SessionStore,
|
|
32
|
+
SQLiteSessionStore,
|
|
33
|
+
MongoSessionStore,
|
|
34
|
+
MemorySessionStore,
|
|
35
|
+
defaultSystemPrompt,
|
|
36
|
+
CronStore,
|
|
37
|
+
MongoCronStore,
|
|
38
|
+
SQLiteCronStore,
|
|
39
|
+
parseInterval,
|
|
40
|
+
HEARTBEAT_INTERVAL_MS,
|
|
41
|
+
HEARTBEAT_PROMPT,
|
|
42
|
+
runWithConcurrency,
|
|
43
|
+
TaskStore,
|
|
44
|
+
MongoTaskStore,
|
|
45
|
+
SQLiteTaskStore,
|
|
46
|
+
// Backwards compatibility aliases
|
|
47
|
+
GoalStore,
|
|
48
|
+
MongoGoalStore,
|
|
49
|
+
SQLiteGoalStore,
|
|
50
|
+
TriggerStore,
|
|
51
|
+
MongoTriggerStore,
|
|
52
|
+
SQLiteTriggerStore,
|
|
53
|
+
SQLiteMemoryStore,
|
|
54
|
+
EventStore,
|
|
55
|
+
SQLiteEventStore,
|
|
56
|
+
} from './storage/index.js';
|
|
57
|
+
|
|
58
|
+
// Export tool system
|
|
59
|
+
export {
|
|
60
|
+
createToolRegistry,
|
|
61
|
+
coreTools,
|
|
62
|
+
memoryTools,
|
|
63
|
+
webTools,
|
|
64
|
+
codeTools,
|
|
65
|
+
fileTools,
|
|
66
|
+
messageTools,
|
|
67
|
+
imageTools,
|
|
68
|
+
weatherTools,
|
|
69
|
+
notifyTools,
|
|
70
|
+
browserTools,
|
|
71
|
+
createBrowserTools,
|
|
72
|
+
taskTools,
|
|
73
|
+
goalTools, // backwards compatibility alias
|
|
74
|
+
triggerTools,
|
|
75
|
+
jobTools,
|
|
76
|
+
cronTools, // backwards compatibility alias
|
|
77
|
+
eventTools,
|
|
78
|
+
appgenTools,
|
|
79
|
+
} from './tools/index.js';
|
|
80
|
+
|
|
81
|
+
// Export provider configuration
|
|
82
|
+
import { AI_PROVIDERS } from './utils/providers.js';
|
|
83
|
+
export { AI_PROVIDERS };
|
|
84
|
+
|
|
85
|
+
// Export agent loop (already well-abstracted)
|
|
86
|
+
export { agentLoop } from './core/agent.js';
|
|
87
|
+
|
|
88
|
+
// Export compaction utilities
|
|
89
|
+
export { compactMessages, estimateTokens } from './core/compaction.js';
|
|
90
|
+
|
|
91
|
+
// Export message normalization
|
|
92
|
+
export { toStandardFormat, toProviderFormat, normalizeMessages } from './core/normalize.js';
|
|
93
|
+
|
|
94
|
+
// Export event system
|
|
95
|
+
export { validateEvent, normalizeStatsEvent } from './core/events.js';
|
|
96
|
+
|
|
97
|
+
// Export unified initialization
|
|
98
|
+
export { init } from './core/init.js';
|
|
99
|
+
|
|
100
|
+
// Export handler factories for advanced use cases
|
|
101
|
+
export { createCronHandler } from './core/cron_handler.js';
|
|
102
|
+
export { createTriggerHandler } from './core/trigger_handler.js';
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Create an agent instance with configurable stores, providers, and tools
|
|
106
|
+
*
|
|
107
|
+
* @param {Object} options - Configuration options
|
|
108
|
+
* @param {SessionStore} options.sessionStore - Session storage backend
|
|
109
|
+
* @param {Object} options.providers - Provider API keys: { anthropic: { apiKey }, openai: { apiKey }, xai: { apiKey }, ollama: { baseUrl } }
|
|
110
|
+
* @param {Function} [options.systemPrompt] - System prompt builder: (agentName, agentPersonality, timestamp) => string
|
|
111
|
+
* @param {Array} [options.tools] - Tool definitions (defaults to coreTools)
|
|
112
|
+
* @param {CronStore} [options.cronStore] - Optional cron storage backend for scheduled tasks
|
|
113
|
+
* @param {TaskStore} [options.taskStore] - Optional task storage backend for multi-step autonomous execution
|
|
114
|
+
* @param {TriggerStore} [options.triggerStore] - Optional trigger storage backend for event-driven responses
|
|
115
|
+
* @param {SQLiteMemoryStore} [options.memoryStore] - Optional memory storage backend for long-term memory
|
|
116
|
+
* @param {EventStore} [options.eventStore] - Optional event storage backend for usage analytics
|
|
117
|
+
* @param {Function} [options.screenshotUrlPattern] - Screenshot URL pattern: (filename) => URL string
|
|
118
|
+
* @param {Object} [options.compaction] - Compaction settings: { enabled: true, ... }
|
|
119
|
+
* @returns {Object} Agent API
|
|
120
|
+
*/
|
|
121
|
+
export function createAgent({
|
|
122
|
+
sessionStore,
|
|
123
|
+
providers = {},
|
|
124
|
+
systemPrompt,
|
|
125
|
+
tools = coreTools,
|
|
126
|
+
cronStore = null,
|
|
127
|
+
taskStore = null,
|
|
128
|
+
triggerStore = null,
|
|
129
|
+
memoryStore = null,
|
|
130
|
+
eventStore = null,
|
|
131
|
+
screenshotUrlPattern = (filename) => `/screenshots/${filename}`,
|
|
132
|
+
compaction = { enabled: true },
|
|
133
|
+
} = {}) {
|
|
134
|
+
if (!sessionStore) {
|
|
135
|
+
throw new Error('createAgent() requires a sessionStore (SessionStore instance)');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// If custom screenshotUrlPattern provided, rebuild browser tools
|
|
139
|
+
let finalTools = tools;
|
|
140
|
+
if (screenshotUrlPattern && tools === coreTools) {
|
|
141
|
+
// Replace default browser tools with customized ones
|
|
142
|
+
const customBrowserTools = createBrowserTools(screenshotUrlPattern);
|
|
143
|
+
finalTools = [
|
|
144
|
+
...memoryTools,
|
|
145
|
+
...webTools,
|
|
146
|
+
...codeTools,
|
|
147
|
+
...fileTools,
|
|
148
|
+
...messageTools,
|
|
149
|
+
...imageTools,
|
|
150
|
+
...weatherTools,
|
|
151
|
+
...notifyTools,
|
|
152
|
+
...customBrowserTools,
|
|
153
|
+
...taskTools,
|
|
154
|
+
...triggerTools,
|
|
155
|
+
...jobTools,
|
|
156
|
+
...eventTools,
|
|
157
|
+
...appgenTools,
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
/**
|
|
163
|
+
* Run agent chat loop with streaming
|
|
164
|
+
*
|
|
165
|
+
* @param {Object} params
|
|
166
|
+
* @param {string} params.sessionId - Session UUID
|
|
167
|
+
* @param {string} params.message - User message
|
|
168
|
+
* @param {string} params.provider - AI provider ID
|
|
169
|
+
* @param {string} params.model - Model name
|
|
170
|
+
* @param {AbortSignal} [params.signal] - Abort signal
|
|
171
|
+
* @param {Object} [params.context] - Tool execution context
|
|
172
|
+
* @returns {AsyncGenerator} SSE event stream
|
|
173
|
+
*/
|
|
174
|
+
async* chat({ sessionId, message, provider, model, signal, context = {} }) {
|
|
175
|
+
// Get session
|
|
176
|
+
const session = await sessionStore.getSessionInternal(sessionId);
|
|
177
|
+
if (!session) throw new Error(`Session ${sessionId} not found`);
|
|
178
|
+
|
|
179
|
+
// Inject providers and stores into context
|
|
180
|
+
const enhancedContext = {
|
|
181
|
+
...context,
|
|
182
|
+
providers,
|
|
183
|
+
cronStore,
|
|
184
|
+
taskStore,
|
|
185
|
+
triggerStore,
|
|
186
|
+
memoryStore,
|
|
187
|
+
eventStore,
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Resolve string provider ID to a full provider config object.
|
|
191
|
+
// agentLoop expects a provider config (with apiUrl, headers, etc.),
|
|
192
|
+
// not a string ID. Inject the API key from the providers config.
|
|
193
|
+
let resolvedProvider = provider;
|
|
194
|
+
if (typeof provider === 'string') {
|
|
195
|
+
const base = AI_PROVIDERS[provider];
|
|
196
|
+
if (base) {
|
|
197
|
+
const apiKey = providers[provider]?.apiKey;
|
|
198
|
+
resolvedProvider = apiKey
|
|
199
|
+
? { ...base, headers: () => base.headers(apiKey) }
|
|
200
|
+
: base;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Run agent loop
|
|
205
|
+
const generator = agentLoop({
|
|
206
|
+
session,
|
|
207
|
+
userMessage: message,
|
|
208
|
+
tools: finalTools,
|
|
209
|
+
provider: resolvedProvider,
|
|
210
|
+
model,
|
|
211
|
+
signal,
|
|
212
|
+
context: enhancedContext,
|
|
213
|
+
compaction: { ...compaction, providers },
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Stream events and save session on completion
|
|
217
|
+
let finalMessages = session.messages;
|
|
218
|
+
let finalModel = model;
|
|
219
|
+
let finalProvider = provider;
|
|
220
|
+
|
|
221
|
+
for await (const event of generator) {
|
|
222
|
+
yield event;
|
|
223
|
+
if (event.type === 'done' && event.messages) {
|
|
224
|
+
finalMessages = event.messages;
|
|
225
|
+
if (event.model) finalModel = event.model;
|
|
226
|
+
if (event.provider) finalProvider = event.provider;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Save session after loop completes
|
|
231
|
+
await sessionStore.saveSession(sessionId, finalMessages, finalModel, finalProvider);
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Create a new session
|
|
236
|
+
*
|
|
237
|
+
* @param {string} owner - User ID
|
|
238
|
+
* @param {string} [model] - Initial model
|
|
239
|
+
* @param {string} [provider] - Initial provider
|
|
240
|
+
* @returns {Promise<Object>} Session document
|
|
241
|
+
*/
|
|
242
|
+
async createSession(owner, model, provider) {
|
|
243
|
+
return await sessionStore.createSession(owner, model, provider);
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Get a session by ID
|
|
248
|
+
*
|
|
249
|
+
* @param {string} sessionId - Session UUID
|
|
250
|
+
* @param {string} owner - User ID
|
|
251
|
+
* @returns {Promise<Object|null>} Session document
|
|
252
|
+
*/
|
|
253
|
+
async getSession(sessionId, owner) {
|
|
254
|
+
return await sessionStore.getSession(sessionId, owner);
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* List sessions for a user
|
|
259
|
+
*
|
|
260
|
+
* @param {string} owner - User ID
|
|
261
|
+
* @returns {Promise<Array>} Session summaries
|
|
262
|
+
*/
|
|
263
|
+
async listSessions(owner) {
|
|
264
|
+
return await sessionStore.listSessions(owner);
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Delete a session
|
|
269
|
+
*
|
|
270
|
+
* @param {string} sessionId - Session UUID
|
|
271
|
+
* @param {string} owner - User ID
|
|
272
|
+
* @returns {Promise<any>} Delete result
|
|
273
|
+
*/
|
|
274
|
+
async deleteSession(sessionId, owner) {
|
|
275
|
+
return await sessionStore.deleteSession(sessionId, owner);
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Clear session conversation history
|
|
280
|
+
*
|
|
281
|
+
* @param {string} sessionId - Session UUID
|
|
282
|
+
*/
|
|
283
|
+
async clearSession(sessionId) {
|
|
284
|
+
await sessionStore.clearSession(sessionId);
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get registered tools
|
|
289
|
+
*
|
|
290
|
+
* @returns {Array} Tool definitions
|
|
291
|
+
*/
|
|
292
|
+
getTools() {
|
|
293
|
+
return finalTools;
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Get cron store (if configured)
|
|
298
|
+
*
|
|
299
|
+
* @returns {CronStore|null} Cron store instance
|
|
300
|
+
*/
|
|
301
|
+
getCronStore() {
|
|
302
|
+
return cronStore;
|
|
303
|
+
},
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get task store (if configured)
|
|
307
|
+
*
|
|
308
|
+
* @returns {TaskStore|null} Task store instance
|
|
309
|
+
*/
|
|
310
|
+
getTaskStore() {
|
|
311
|
+
return taskStore;
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Get trigger store (if configured)
|
|
316
|
+
*
|
|
317
|
+
* @returns {TriggerStore|null} Trigger store instance
|
|
318
|
+
*/
|
|
319
|
+
getTriggerStore() {
|
|
320
|
+
return triggerStore;
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Get memory store (if configured)
|
|
325
|
+
*
|
|
326
|
+
* @returns {SQLiteMemoryStore|null} Memory store instance
|
|
327
|
+
*/
|
|
328
|
+
getMemoryStore() {
|
|
329
|
+
return memoryStore;
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Get event store (if configured)
|
|
334
|
+
*
|
|
335
|
+
* @returns {EventStore|null} Event store instance
|
|
336
|
+
*/
|
|
337
|
+
getEventStore() {
|
|
338
|
+
return eventStore;
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
}
|