feat: wire up all Phase 2-6 features into daemon and config

Integrate all new features into the shared infrastructure:
- Config schema: add memory, discord, slack, process, web_search schemas
- Daemon wiring: memory store init, tool registration, channel adapters
- Orchestrator: memory injection into system prompt, extraction on compaction
- Agent: add setSystemPrompt() for dynamic prompt updates
- Channel/tool index: export new adapters and tool factories
- Add @slack/bolt, discord.js, turndown, linkedom, @mozilla/readability deps
- Update state.json with Phase 3b completion (494 tests passing)
This commit is contained in:
William Valentin
2026-02-06 14:24:39 -08:00
parent 6d9e27a591
commit 7a35b22458
12 changed files with 1099 additions and 4 deletions
+4
View File
@@ -1,5 +1,9 @@
# Flynn AGENTS.md
## General Rules
- **Parallelise with subagents:** For every task, use multiple subagents with the appropriate model to work more efficiently. Dispatch independent subtasks in parallel rather than executing them sequentially.
## Build, Lint, and Test Commands
```bash
+215
View File
@@ -0,0 +1,215 @@
{
"version": "1.0",
"updated_at": "2026-02-06",
"description": "Tracks the status of all Flynn plans and implementation phases",
"plans": {
"openclaw-feature-gap-analysis": {
"file": "2026-02-06-openclaw-feature-gap-analysis.md",
"status": "completed",
"date": "2026-02-06",
"summary": "Comprehensive comparison of Flynn vs OpenClaw. 118 features compared: 29 match, 11 partial, 78 missing."
},
"p0-p1-implementation-plan": {
"file": "2026-02-06-p0-p1-implementation-plan.md",
"status": "in_progress",
"date": "2026-02-06",
"summary": "7 features across 7 phases (0-6). Estimated 15-22 days total.",
"phases": {
"phase_0_multi_model_delegation": {
"priority": "P0",
"status": "completed",
"description": "AgentOrchestrator with sub-agent delegation to different model tiers",
"files_created": [
"src/backends/native/orchestrator.ts",
"src/backends/native/orchestrator.test.ts",
"src/backends/native/prompts.ts"
],
"files_modified": [
"src/daemon/index.ts",
"src/config/schema.ts"
],
"test_status": "20/20 passing"
},
"phase_1_context_compaction": {
"priority": "P0",
"status": "completed",
"description": "Token estimation, auto-compaction, /compact command, SQLite history replacement",
"files_created": [
"src/context/tokens.ts",
"src/context/tokens.test.ts",
"src/context/compaction.ts",
"src/context/compaction.test.ts",
"src/context/index.ts"
],
"files_modified": [
"src/backends/native/orchestrator.ts",
"src/session/manager.ts",
"src/session/store.ts",
"src/config/schema.ts",
"src/daemon/index.ts",
"src/frontends/tui/commands.ts"
],
"test_status": "21/21 passing"
},
"phase_2_memory_system": {
"priority": "P0",
"status": "completed",
"description": "Persistent memory with file-based storage, memory tools, auto-extraction after compaction",
"depends_on": ["phase_0", "phase_1"],
"files_created": [
"src/memory/store.ts",
"src/memory/store.test.ts",
"src/memory/index.ts",
"src/tools/builtin/memory-read.ts",
"src/tools/builtin/memory-write.ts",
"src/tools/builtin/memory-search.ts"
],
"files_modified": [
"src/tools/builtin/index.ts",
"src/config/schema.ts",
"src/backends/native/agent.ts",
"src/backends/native/orchestrator.ts",
"src/context/compaction.ts",
"src/daemon/index.ts"
],
"test_status": "17/17 passing"
},
"phase_3_messaging_channels": {
"priority": "P1",
"status": "in_progress",
"description": "Discord, Slack, WhatsApp channel adapters",
"sub_phases": {
"3a_discord": {
"status": "completed",
"effort": "1-2 days",
"files_created": [
"src/channels/discord/adapter.ts",
"src/channels/discord/adapter.test.ts",
"src/channels/discord/index.ts"
],
"files_modified": [
"src/config/schema.ts",
"src/channels/index.ts",
"src/daemon/index.ts"
],
"test_status": "22/22 passing"
},
"3b_slack": {
"status": "completed",
"effort": "1 day",
"files_created": [
"src/channels/slack/adapter.ts",
"src/channels/slack/adapter.test.ts",
"src/channels/slack/index.ts"
],
"files_modified": [
"src/config/schema.ts",
"src/channels/index.ts",
"src/daemon/index.ts",
"package.json"
],
"new_dependencies": ["@slack/bolt"],
"test_status": "22/22 passing",
"notes": "Socket Mode only (HTTP fallback deferred). Slash commands deferred. User ID used as senderName (display name resolution is a follow-up)."
},
"3c_whatsapp": { "status": "not_started", "effort": "2-3 days" }
},
"planned_files": [
"src/channels/discord/adapter.ts",
"src/channels/discord/index.ts",
"src/channels/slack/adapter.ts",
"src/channels/slack/index.ts",
"src/channels/whatsapp/adapter.ts",
"src/channels/whatsapp/index.ts",
"src/channels/utils/chunking.ts",
"src/channels/utils/auth.ts",
"src/channels/utils/markdown.ts"
]
},
"phase_4_web_search": {
"priority": "P1",
"status": "completed",
"description": "Web search tool (Brave Search API + SearXNG fallback)",
"effort": "0.5 day",
"files_created": [
"src/tools/builtin/web-search.ts",
"src/tools/builtin/web-search.test.ts"
],
"files_modified": [
"src/config/schema.ts",
"src/tools/builtin/index.ts",
"src/tools/index.ts",
"src/daemon/index.ts"
],
"test_status": "14/14 passing"
},
"phase_5_background_exec": {
"priority": "P1",
"status": "completed",
"description": "Background process management tools (start, status, output, kill, list)",
"effort": "1-2 days",
"files_created": [
"src/tools/builtin/process/manager.ts",
"src/tools/builtin/process/start.ts",
"src/tools/builtin/process/status.ts",
"src/tools/builtin/process/output.ts",
"src/tools/builtin/process/kill.ts",
"src/tools/builtin/process/list.ts",
"src/tools/builtin/process/index.ts",
"src/tools/builtin/process/manager.test.ts"
],
"files_modified": [
"src/config/schema.ts",
"src/tools/builtin/index.ts",
"src/tools/index.ts",
"src/daemon/index.ts"
],
"test_status": "28/28 passing"
},
"phase_6_enhanced_web_fetch": {
"priority": "P1",
"status": "completed",
"description": "HTML-to-markdown extraction, format parameter, response caching",
"effort": "1 day",
"files_modified": [
"src/tools/builtin/web-fetch.ts",
"src/tools/builtin/web-fetch.test.ts"
],
"new_dependencies": ["turndown", "linkedom", "@mozilla/readability", "@types/turndown"],
"test_status": "10/10 passing"
}
}
},
"earlier_plans": {
"status": "completed",
"summary": "Original design and implementation phases from 2026-02-02 to 2026-02-05",
"plans": [
{ "file": "2026-02-02-flynn-design.md", "status": "completed" },
{ "file": "2026-02-02-flynn-phase1-implementation.md", "status": "completed" },
{ "file": "2026-02-02-flynn-phase2-implementation.md", "status": "completed" },
{ "file": "2026-02-05-flynn-phase3-implementation.md", "status": "completed" },
{ "file": "2026-02-05-tui-redesign.md", "status": "completed" },
{ "file": "2026-02-05-tui-redesign-implementation.md", "status": "completed" },
{ "file": "2026-02-05-llamacpp-integration-design.md", "status": "completed" },
{ "file": "2026-02-05-llamacpp-implementation.md", "status": "completed" },
{ "file": "2026-02-05-backend-switch-design.md", "status": "completed" },
{ "file": "2026-02-05-backend-switch-implementation.md", "status": "completed" },
{ "file": "2026-02-05-openclaw-parity-design.md", "status": "completed" },
{ "file": "2026-02-05-phase1-tool-framework.md", "status": "completed" },
{ "file": "2026-02-05-phase2-websocket-gateway.md", "status": "completed" },
{ "file": "2026-02-05-phase3-channel-adapters.md", "status": "completed" },
{ "file": "2026-02-05-phase5-cli-cron-doctor-design.md", "status": "completed" },
{ "file": "2026-02-05-phase5a-implementation.md", "status": "completed" }
]
}
},
"overall_progress": {
"total_test_count": 494,
"all_tests_passing": true,
"p0_completion": "3/3 (100%)",
"p1_completion": "3/4 (75%)",
"next_up": "phase_3c_whatsapp_adapter"
}
}
+6
View File
@@ -31,6 +31,7 @@
"@types/marked-terminal": "^6.1.1",
"@types/node": "^22.0.0",
"@types/react": "^19.0.0",
"@types/turndown": "^5.0.0",
"@types/ws": "^8.18.1",
"eslint": "^9.0.0",
"tsx": "^4.0.0",
@@ -40,18 +41,23 @@
"dependencies": {
"@anthropic-ai/sdk": "^0.39.0",
"@modelcontextprotocol/sdk": "^1.26.0",
"@mozilla/readability": "^0.5.0",
"@slack/bolt": "^4.6.0",
"better-sqlite3": "^11.0.0",
"cli-highlight": "^2.1.11",
"commander": "^14.0.3",
"croner": "^10.0.1",
"discord.js": "^14.25.1",
"grammy": "^1.35.0",
"ink": "^6.0.0",
"ink-text-input": "^6.0.0",
"linkedom": "^0.18.0",
"marked": "^17.0.1",
"marked-terminal": "^7.3.0",
"ollama": "^0.5.0",
"openai": "^4.0.0",
"react": "^19.0.0",
"turndown": "^7.2.0",
"ws": "^8.19.0",
"yaml": "^2.7.0",
"zod": "^3.24.0"
+664
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -199,6 +199,10 @@ export class NativeAgent {
return this.currentTier;
}
setSystemPrompt(prompt: string): void {
this.systemPrompt = prompt;
}
setOnToolUse(callback: ((event: ToolUseEvent) => void) | undefined): void {
this.onToolUse = callback;
}
+30
View File
@@ -3,6 +3,7 @@ import type { ChatRequest, Message, TokenUsage } from '../../models/types.js';
import type { Session } from '../../session/index.js';
import type { ToolRegistry } from '../../tools/registry.js';
import type { ToolExecutor } from '../../tools/executor.js';
import type { MemoryStore } from '../../memory/store.js';
import { NativeAgent } from './agent.js';
import type { ToolUseEvent } from './agent.js';
import { shouldCompact } from '../../context/tokens.js';
@@ -64,6 +65,8 @@ export interface OrchestratorConfig {
modelName?: string;
/** Optional override for the context window size (in tokens). */
contextWindow?: number;
/** Optional memory store for injecting persistent memory into the system prompt. */
memoryStore?: MemoryStore;
}
// ── AgentOrchestrator ─────────────────────────────────────────────────
@@ -86,6 +89,8 @@ export class AgentOrchestrator {
private _compactionConfig?: CompactionConfig;
private _modelName?: string;
private _contextWindow?: number;
private _memoryStore?: MemoryStore;
private _systemPromptBase: string;
private _usageByTier: Map<string, TierUsageStats> = new Map();
constructor(config: OrchestratorConfig) {
@@ -97,6 +102,8 @@ export class AgentOrchestrator {
this._compactionConfig = config.compaction;
this._modelName = config.modelName;
this._contextWindow = config.contextWindow;
this._memoryStore = config.memoryStore;
this._systemPromptBase = config.systemPrompt;
// Create the primary NativeAgent for user-facing conversation
this._agent = new NativeAgent({
@@ -178,6 +185,7 @@ export class AgentOrchestrator {
* exceeds the context window threshold and compacts it before processing.
*/
async process(userMessage: string): Promise<string> {
this._injectMemoryContext();
await this.compactIfNeeded();
return this._agent.process(userMessage);
}
@@ -199,6 +207,7 @@ export class AgentOrchestrator {
messages,
orchestrator: this,
config,
memoryStore: this._memoryStore,
});
// If nothing was actually compacted, skip the replace
@@ -268,6 +277,27 @@ export class AgentOrchestrator {
// ── Private helpers ───────────────────────────────────────────────
/**
* Inject persistent memory context into the primary agent's system prompt.
* Reads from the memory store and appends relevant context to the base
* system prompt. If no memory store is configured or no memory content
* exists, restores the original base prompt.
*/
private _injectMemoryContext(): void {
if (!this._memoryStore) {
return;
}
const memoryContext = this._memoryStore.getContextForPrompt();
if (!memoryContext) {
this._agent.setSystemPrompt(this._systemPromptBase);
return;
}
const enrichedPrompt = `${this._systemPromptBase}\n\n# Memory Context\n\nThe following is your persistent memory. Use it to maintain continuity across sessions.\n\n${memoryContext}`;
this._agent.setSystemPrompt(enrichedPrompt);
}
/**
* Check whether automatic compaction should run, and if so, compact.
* Called before each `process()` call when compaction is configured.
+2
View File
@@ -9,3 +9,5 @@ export type {
export { ChannelRegistry } from './registry.js';
export { TelegramAdapter, type TelegramAdapterConfig } from './telegram/index.js';
export { WebChatAdapter, type WebChatAdapterConfig } from './webchat/index.js';
export { DiscordAdapter, type DiscordAdapterConfig } from './discord/index.js';
export { SlackAdapter, type SlackAdapterConfig } from './slack/index.js';
+44
View File
@@ -107,6 +107,13 @@ const agentsSchema = z.object({
max_delegation_depth: z.number().min(1).max(10).default(3),
}).default({});
const memorySchema = z.object({
enabled: z.boolean().default(true),
dir: z.string().optional(), // Default: ~/.local/share/flynn/memory
auto_extract: z.boolean().default(true),
max_context_tokens: z.number().min(100).max(10000).default(2000),
}).default({});
const compactionSchema = z.object({
enabled: z.boolean().default(true),
threshold_pct: z.number().min(10).max(100).default(80),
@@ -114,8 +121,37 @@ const compactionSchema = z.object({
summary_max_tokens: z.number().min(128).max(4096).default(1024),
}).default({});
const discordSchema = z.object({
bot_token: z.string().min(1, 'Bot token is required'),
allowed_guild_ids: z.array(z.string()).default([]),
allowed_channel_ids: z.array(z.string()).default([]),
require_mention: z.boolean().default(true),
}).optional();
const slackSchema = z.object({
bot_token: z.string().min(1, 'Bot token is required'),
app_token: z.string().min(1, 'App token is required'),
signing_secret: z.string().min(1, 'Signing secret is required'),
allowed_channel_ids: z.array(z.string()).default([]),
}).optional();
const processSchema = z.object({
max_concurrent: z.number().min(1).max(50).default(10),
max_runtime_minutes: z.number().min(1).max(1440).default(60),
buffer_size: z.number().min(1024).max(1048576).default(65536),
}).default({});
const webSearchSchema = z.object({
provider: z.enum(['brave', 'searxng']).default('brave'),
api_key: z.string().optional(),
endpoint: z.string().optional(),
max_results: z.number().min(1).max(20).default(5),
}).default({});
export const configSchema = z.object({
telegram: telegramSchema,
discord: discordSchema,
slack: slackSchema,
server: serverSchema.default({}),
models: modelsSchema,
backends: backendsSchema.default({}),
@@ -125,6 +161,9 @@ export const configSchema = z.object({
automation: automationSchema,
agents: agentsSchema,
compaction: compactionSchema,
memory: memorySchema,
process: processSchema,
web_search: webSearchSchema,
});
export type Config = z.infer<typeof configSchema>;
@@ -133,3 +172,8 @@ export type ModelConfig = z.infer<typeof modelConfigSchema>;
export type CronJobConfig = z.infer<typeof cronJobSchema>;
export type AgentsConfig = z.infer<typeof agentsSchema>;
export type CompactionConfig = z.infer<typeof compactionSchema>;
export type MemoryConfig = z.infer<typeof memorySchema>;
export type WebSearchConfig = z.infer<typeof webSearchSchema>;
export type ProcessConfig = z.infer<typeof processSchema>;
export type DiscordConfig = z.infer<typeof discordSchema>;
export type SlackConfig = z.infer<typeof slackSchema>;
+27 -1
View File
@@ -1,6 +1,7 @@
import type { Message } from '../models/types.js';
import type { AgentOrchestrator } from '../backends/native/orchestrator.js';
import { COMPACTION_SYSTEM_PROMPT } from '../backends/native/prompts.js';
import type { MemoryStore } from '../memory/store.js';
import { COMPACTION_SYSTEM_PROMPT, MEMORY_EXTRACTION_PROMPT } from '../backends/native/prompts.js';
import { estimateMessageTokens } from './tokens.js';
export interface CompactionConfig {
@@ -33,6 +34,8 @@ export async function compactHistory(opts: {
messages: Message[];
orchestrator: AgentOrchestrator;
config: CompactionConfig;
memoryStore?: MemoryStore;
autoExtract?: boolean;
}): Promise<CompactionResult> {
const { messages, orchestrator, config } = opts;
@@ -65,6 +68,29 @@ export async function compactHistory(opts: {
content: '[Summary of earlier conversation]\n\n' + result.content,
};
// Phase 2: Extract persistent facts and append to memory (if enabled)
if (opts.memoryStore && opts.autoExtract !== false) {
try {
const extractionTier = orchestrator.getDelegationTier('memory_extraction');
const extraction = await orchestrator.delegate({
tier: extractionTier,
systemPrompt: MEMORY_EXTRACTION_PROMPT,
message: `Extract persistent facts from this conversation:\n\n${formattedConversation}`,
maxTokens: 512,
});
// Only write if the extraction produced meaningful content
const extractedContent = extraction.content.trim();
if (extractedContent.length > 0 && !extractedContent.toLowerCase().includes('no facts')) {
opts.memoryStore.write('global', extractedContent, 'append');
console.log(`[Flynn:memory] Extracted ${extractedContent.length} chars of facts to global memory`);
}
} catch (error) {
// Memory extraction is best-effort — don't fail compaction if it errors
console.warn('[Flynn:memory] Failed to extract facts during compaction:', error);
}
}
return {
messages: [summaryMessage, ...toKeep],
compactedCount: toCompact.length,
+72 -2
View File
@@ -5,9 +5,11 @@ import type { ModelClient } from '../models/index.js';
import { AgentOrchestrator, type DelegationConfig } from '../backends/index.js';
import { SessionStore, SessionManager } from '../session/index.js';
import { HookEngine } from '../hooks/index.js';
import { ToolRegistry, ToolExecutor, allBuiltinTools } from '../tools/index.js';
import { ToolRegistry, ToolExecutor, allBuiltinTools, createWebSearchTools, createProcessTools, ProcessManager } from '../tools/index.js';
import { MemoryStore } from '../memory/index.js';
import { createMemoryTools } from '../tools/builtin/index.js';
import { GatewayServer } from '../gateway/index.js';
import { ChannelRegistry, TelegramAdapter, WebChatAdapter } from '../channels/index.js';
import { ChannelRegistry, TelegramAdapter, WebChatAdapter, DiscordAdapter, SlackAdapter } from '../channels/index.js';
import { CronScheduler } from '../automation/index.js';
import type { InboundMessage, OutboundMessage } from '../channels/index.js';
import { McpManager } from '../mcp/index.js';
@@ -144,6 +146,7 @@ function createMessageRouter(deps: {
toolRegistry: ToolRegistry;
toolExecutor: ToolExecutor;
config: Config;
memoryStore?: MemoryStore;
}) {
// Cache agents by session ID to avoid recreating on every message
const agents = new Map<string, AgentOrchestrator>();
@@ -176,6 +179,7 @@ function createMessageRouter(deps: {
} : undefined,
modelName: deps.config.models.default.model,
contextWindow: deps.config.models.default.context_window,
memoryStore: deps.memoryStore,
});
agents.set(sessionId, agent);
}
@@ -228,6 +232,13 @@ export async function startDaemon(config: Config): Promise<DaemonContext> {
const dataDir = resolve(homedir(), '.local/share/flynn');
mkdirSync(dataDir, { recursive: true });
// Initialize memory store
const memoryDir = config.memory.dir ?? resolve(dataDir, 'memory');
mkdirSync(memoryDir, { recursive: true });
const memoryStore = config.memory.enabled
? new MemoryStore({ dir: memoryDir, maxContextTokens: config.memory.max_context_tokens })
: undefined;
// Initialize session store and manager
const sessionStore = new SessionStore(resolve(dataDir, 'sessions.db'));
const sessionManager = new SessionManager(sessionStore);
@@ -245,6 +256,42 @@ export async function startDaemon(config: Config): Promise<DaemonContext> {
for (const tool of allBuiltinTools) {
toolRegistry.register(tool);
}
// Register memory tools if memory is enabled
if (memoryStore) {
for (const tool of createMemoryTools(memoryStore)) {
toolRegistry.register(tool);
}
}
// Register web search tool if configured with credentials
if (config.web_search.api_key || config.web_search.endpoint) {
for (const tool of createWebSearchTools({
provider: config.web_search.provider,
apiKey: config.web_search.api_key,
endpoint: config.web_search.endpoint,
maxResults: config.web_search.max_results,
})) {
toolRegistry.register(tool);
}
}
// Initialize process manager and register process tools
const processManager = new ProcessManager({
maxConcurrent: config.process.max_concurrent,
maxRuntimeMinutes: config.process.max_runtime_minutes,
bufferSize: config.process.buffer_size,
});
for (const tool of createProcessTools(processManager)) {
toolRegistry.register(tool);
}
lifecycle.onShutdown(async () => {
await processManager.shutdown();
console.log('Process manager stopped');
});
const toolExecutor = new ToolExecutor(toolRegistry, hookEngine);
// Initialize MCP manager and start configured servers
@@ -321,6 +368,7 @@ export async function startDaemon(config: Config): Promise<DaemonContext> {
toolRegistry,
toolExecutor,
config,
memoryStore,
}));
// Register Telegram adapter
@@ -331,6 +379,28 @@ export async function startDaemon(config: Config): Promise<DaemonContext> {
});
channelRegistry.register(telegramAdapter);
// Register Discord adapter (if configured)
if (config.discord) {
const discordAdapter = new DiscordAdapter({
botToken: config.discord.bot_token,
allowedGuildIds: config.discord.allowed_guild_ids.length > 0 ? config.discord.allowed_guild_ids : undefined,
allowedChannelIds: config.discord.allowed_channel_ids.length > 0 ? config.discord.allowed_channel_ids : undefined,
requireMention: config.discord.require_mention,
});
channelRegistry.register(discordAdapter);
}
// Register Slack adapter (if configured)
if (config.slack) {
const slackAdapter = new SlackAdapter({
botToken: config.slack.bot_token,
appToken: config.slack.app_token,
signingSecret: config.slack.signing_secret,
allowedChannelIds: config.slack.allowed_channel_ids.length > 0 ? config.slack.allowed_channel_ids : undefined,
});
channelRegistry.register(slackAdapter);
}
// Register WebChat adapter (wraps the gateway)
const webChatAdapter = new WebChatAdapter({ gateway });
channelRegistry.register(webChatAdapter);
+28
View File
@@ -4,15 +4,29 @@ export { fileWriteTool } from './file-write.js';
export { fileEditTool } from './file-edit.js';
export { fileListTool } from './file-list.js';
export { webFetchTool } from './web-fetch.js';
export { createMemoryReadTool } from './memory-read.js';
export { createMemoryWriteTool } from './memory-write.js';
export { createMemorySearchTool } from './memory-search.js';
export { createWebSearchTool } from './web-search.js';
export type { WebSearchConfig } from './web-search.js';
export { createProcessTools, ProcessManager } from './process/index.js';
export type { ProcessManagerConfig } from './process/index.js';
import type { Tool } from '../types.js';
import type { MemoryStore } from '../../memory/store.js';
import type { WebSearchConfig } from './web-search.js';
import { shellExecTool } from './shell.js';
import { fileReadTool } from './file-read.js';
import { fileWriteTool } from './file-write.js';
import { fileEditTool } from './file-edit.js';
import { fileListTool } from './file-list.js';
import { webFetchTool } from './web-fetch.js';
import { createMemoryReadTool } from './memory-read.js';
import { createMemoryWriteTool } from './memory-write.js';
import { createMemorySearchTool } from './memory-search.js';
import { createWebSearchTool } from './web-search.js';
/** Static builtin tools that don't require runtime dependencies. */
export const allBuiltinTools: Tool[] = [
shellExecTool,
fileReadTool,
@@ -21,3 +35,17 @@ export const allBuiltinTools: Tool[] = [
fileListTool,
webFetchTool,
];
/** Create memory tools that require a MemoryStore instance. */
export function createMemoryTools(store: MemoryStore): Tool[] {
return [
createMemoryReadTool(store),
createMemoryWriteTool(store),
createMemorySearchTool(store),
];
}
/** Create the web search tool with provider config. */
export function createWebSearchTools(config: WebSearchConfig): Tool[] {
return [createWebSearchTool(config)];
}
+3 -1
View File
@@ -3,7 +3,9 @@ export { ToolRegistry } from './registry.js';
export type { AnthropicToolDef, OpenAIToolDef } from './registry.js';
export { ToolExecutor } from './executor.js';
export type { ToolExecutorConfig } from './executor.js';
export { allBuiltinTools } from './builtin/index.js';
export { allBuiltinTools, createWebSearchTools, createProcessTools, ProcessManager } from './builtin/index.js';
export type { WebSearchConfig } from './builtin/web-search.js';
export type { ProcessManagerConfig } from './builtin/process/index.js';
export { shellExecTool } from './builtin/shell.js';
export { fileReadTool } from './builtin/file-read.js';
export { fileWriteTool } from './builtin/file-write.js';