Spaces:
Paused
Paused
| import { Type } from "@sinclair/typebox"; | |
| import type { OpenClawConfig } from "../../config/config.js"; | |
| import type { AnyAgentTool } from "./common.js"; | |
| import { getMemorySearchManager } from "../../memory/index.js"; | |
| import { resolveSessionAgentId } from "../agent-scope.js"; | |
| import { resolveMemorySearchConfig } from "../memory-search.js"; | |
| import { jsonResult, readNumberParam, readStringParam } from "./common.js"; | |
| const MemorySearchSchema = Type.Object({ | |
| query: Type.String(), | |
| maxResults: Type.Optional(Type.Number()), | |
| minScore: Type.Optional(Type.Number()), | |
| }); | |
| const MemoryGetSchema = Type.Object({ | |
| path: Type.String(), | |
| from: Type.Optional(Type.Number()), | |
| lines: Type.Optional(Type.Number()), | |
| }); | |
| export function createMemorySearchTool(options: { | |
| config?: OpenClawConfig; | |
| agentSessionKey?: string; | |
| }): AnyAgentTool | null { | |
| const cfg = options.config; | |
| if (!cfg) { | |
| return null; | |
| } | |
| const agentId = resolveSessionAgentId({ | |
| sessionKey: options.agentSessionKey, | |
| config: cfg, | |
| }); | |
| if (!resolveMemorySearchConfig(cfg, agentId)) { | |
| return null; | |
| } | |
| return { | |
| label: "Memory Search", | |
| name: "memory_search", | |
| description: | |
| "Mandatory recall step: semantically search MEMORY.md + memory/*.md (and optional session transcripts) before answering questions about prior work, decisions, dates, people, preferences, or todos; returns top snippets with path + lines.", | |
| parameters: MemorySearchSchema, | |
| execute: async (_toolCallId, params) => { | |
| const query = readStringParam(params, "query", { required: true }); | |
| const maxResults = readNumberParam(params, "maxResults"); | |
| const minScore = readNumberParam(params, "minScore"); | |
| const { manager, error } = await getMemorySearchManager({ | |
| cfg, | |
| agentId, | |
| }); | |
| if (!manager) { | |
| return jsonResult({ results: [], disabled: true, error }); | |
| } | |
| try { | |
| const results = await manager.search(query, { | |
| maxResults, | |
| minScore, | |
| sessionKey: options.agentSessionKey, | |
| }); | |
| const status = manager.status(); | |
| return jsonResult({ | |
| results, | |
| provider: status.provider, | |
| model: status.model, | |
| fallback: status.fallback, | |
| }); | |
| } catch (err) { | |
| const message = err instanceof Error ? err.message : String(err); | |
| return jsonResult({ results: [], disabled: true, error: message }); | |
| } | |
| }, | |
| }; | |
| } | |
| export function createMemoryGetTool(options: { | |
| config?: OpenClawConfig; | |
| agentSessionKey?: string; | |
| }): AnyAgentTool | null { | |
| const cfg = options.config; | |
| if (!cfg) { | |
| return null; | |
| } | |
| const agentId = resolveSessionAgentId({ | |
| sessionKey: options.agentSessionKey, | |
| config: cfg, | |
| }); | |
| if (!resolveMemorySearchConfig(cfg, agentId)) { | |
| return null; | |
| } | |
| return { | |
| label: "Memory Get", | |
| name: "memory_get", | |
| description: | |
| "Safe snippet read from MEMORY.md, memory/*.md, or configured memorySearch.extraPaths with optional from/lines; use after memory_search to pull only the needed lines and keep context small.", | |
| parameters: MemoryGetSchema, | |
| execute: async (_toolCallId, params) => { | |
| const relPath = readStringParam(params, "path", { required: true }); | |
| const from = readNumberParam(params, "from", { integer: true }); | |
| const lines = readNumberParam(params, "lines", { integer: true }); | |
| const { manager, error } = await getMemorySearchManager({ | |
| cfg, | |
| agentId, | |
| }); | |
| if (!manager) { | |
| return jsonResult({ path: relPath, text: "", disabled: true, error }); | |
| } | |
| try { | |
| const result = await manager.readFile({ | |
| relPath, | |
| from: from ?? undefined, | |
| lines: lines ?? undefined, | |
| }); | |
| return jsonResult(result); | |
| } catch (err) { | |
| const message = err instanceof Error ? err.message : String(err); | |
| return jsonResult({ path: relPath, text: "", disabled: true, error: message }); | |
| } | |
| }, | |
| }; | |
| } | |