| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- // index.ts
- import axios from "axios";
- const DEFAULT_BASE_URL = "http://192.168.0.200:8420";
- const DEFAULT_TIMEOUT_MS = 10000;
- const DEFAULT_KNOWLEDGE_USER_ID = "knowledge_base";
- interface MemoryOptions {
- text?: string;
- query?: string;
- userId?: string;
- limit?: number;
- }
- interface KnowledgeOptions {
- query?: string;
- userId?: string;
- limit?: number;
- sourceFile?: string;
- sourceFiles?: string[];
- }
- function getBaseUrl(plugin: any): string {
- return (
- plugin?.config?.baseUrl ||
- process.env.MEM0_BASE_URL ||
- DEFAULT_BASE_URL
- );
- }
- function getDefaultUserId(plugin: any): string {
- return (
- plugin?.runtime?.agent?.id ||
- (globalThis as any)?.openclaw?.agent?.id ||
- plugin?.config?.userId ||
- "default"
- );
- }
- function getKnowledgeUserId(plugin: any): string {
- return (
- plugin?.config?.knowledgeUserId ||
- process.env.MEM0_KNOWLEDGE_USER_ID ||
- DEFAULT_KNOWLEDGE_USER_ID
- );
- }
- function http(plugin: any) {
- return axios.create({
- baseURL: getBaseUrl(plugin),
- timeout: DEFAULT_TIMEOUT_MS,
- });
- }
- function normalizeSourceFile(value?: string): string | undefined {
- if (!value) return undefined;
- const trimmed = value.trim();
- return trimmed.length > 0 ? trimmed : undefined;
- }
- function buildSourceQuery(sourceFile: string): string {
- return sourceFile
- .replace(/\.pdf$/i, "")
- .replace(/[-_]/g, " ")
- .trim();
- }
- function filterBySource(results: any[], sourceFile: string) {
- return results.filter(
- (r) => r?.metadata?.source_file && r.metadata.source_file === sourceFile
- );
- }
- function summarizeKnowledgeResults(results: any[]) {
- const pages = results
- .map((r) => r?.metadata?.page)
- .filter((v) => typeof v === "number") as number[];
- const chapters = results
- .map((r) => r?.metadata?.chapter)
- .filter((v) => typeof v === "number") as number[];
- const created = results
- .map((r) => r?.created_at)
- .filter((v) => typeof v === "string") as string[];
- return {
- count: results.length,
- pageRange: pages.length ? [Math.min(...pages), Math.max(...pages)] : null,
- chapterRange: chapters.length
- ? [Math.min(...chapters), Math.max(...chapters)]
- : null,
- createdAtRange: created.length
- ? [created.sort()[0], created.sort()[created.length - 1]]
- : null,
- };
- }
- export const activate = (plugin: any) => {
- const client = http(plugin);
- // write conversational memory
- plugin.write = async ({ text, userId }: MemoryOptions) => {
- const finalUserId = userId || getDefaultUserId(plugin);
- if (!text) throw new Error("Missing text for memory write");
- const res = await client.post(`/memories`, { text, userId: finalUserId });
- return res.data;
- };
- // search conversational memory
- plugin.search = async ({ query, userId }: MemoryOptions) => {
- const finalUserId = userId || getDefaultUserId(plugin);
- if (!query) throw new Error("Missing query for memory search");
- const res = await client.post(`/memories/search`, {
- query,
- userId: finalUserId,
- });
- return res.data;
- };
- // search knowledge base
- plugin.searchKnowledge = async ({ query, userId, limit }: KnowledgeOptions) => {
- const finalUserId = userId || getKnowledgeUserId(plugin);
- if (!query) throw new Error("Missing query for knowledge search");
- const res = await client.post(`/knowledge/search`, {
- query,
- userId: finalUserId,
- limit,
- });
- return res.data;
- };
- // list knowledge sources (books)
- plugin.listKnowledgeSources = async ({ userId }: KnowledgeOptions = {}) => {
- const finalUserId = userId || getKnowledgeUserId(plugin);
- const res = await client.post(`/knowledge/sources`, {
- user_id: finalUserId,
- });
- return res.data;
- };
- // describe a single book by source_file (metadata summary)
- plugin.describeKnowledgeBook = async ({ sourceFile, userId }: KnowledgeOptions) => {
- const finalUserId = userId || getKnowledgeUserId(plugin);
- const normalized = normalizeSourceFile(sourceFile);
- if (!normalized) throw new Error("Missing sourceFile for knowledge describe");
- const res = await client.post(`/knowledge/search`, {
- query: buildSourceQuery(normalized),
- userId: finalUserId,
- limit: 200,
- });
- const filtered = filterBySource(res.data?.results || [], normalized);
- const summary = summarizeKnowledgeResults(filtered);
- return {
- sourceFile: normalized,
- summary,
- sample: filtered.slice(0, 5),
- hintQuery: buildSourceQuery(normalized),
- };
- };
- // search within a single book (client-side filtered)
- plugin.searchKnowledgeBook = async ({ query, sourceFile, userId, limit = 8 }: KnowledgeOptions) => {
- const finalUserId = userId || getKnowledgeUserId(plugin);
- const normalized = normalizeSourceFile(sourceFile);
- if (!query) throw new Error("Missing query for knowledge search");
- if (!normalized) throw new Error("Missing sourceFile for book search");
- const res = await client.post(`/knowledge/search`, {
- query,
- userId: finalUserId,
- limit: Math.max(limit, 20),
- });
- const filtered = filterBySource(res.data?.results || [], normalized);
- return {
- sourceFile: normalized,
- results: filtered.slice(0, limit),
- };
- };
- // search across a set of books
- plugin.searchKnowledgeBooks = async ({ query, sourceFiles, userId, limit = 8 }: KnowledgeOptions) => {
- const finalUserId = userId || getKnowledgeUserId(plugin);
- if (!query) throw new Error("Missing query for knowledge search");
- if (!Array.isArray(sourceFiles) || sourceFiles.length === 0) {
- throw new Error("Missing sourceFiles for multi-book search");
- }
- const res = await client.post(`/knowledge/search`, {
- query,
- userId: finalUserId,
- limit: Math.max(limit * 3, 20),
- });
- const normalizedSources = sourceFiles
- .map((s) => normalizeSourceFile(s))
- .filter(Boolean) as string[];
- const filtered = (res.data?.results || []).filter((r: any) =>
- normalizedSources.includes(r?.metadata?.source_file)
- );
- return {
- sourceFiles: normalizedSources,
- results: filtered.slice(0, limit),
- };
- };
- // write to knowledge base
- plugin.writeKnowledge = async ({ text, userId }: MemoryOptions) => {
- const finalUserId = userId || getKnowledgeUserId(plugin);
- if (!text) throw new Error("Missing text for knowledge write");
- const res = await client.post(`/knowledge`, { text, userId: finalUserId });
- return res.data;
- };
- // read/recall recent memories (requires /memories/recent on server)
- plugin.read = async ({ userId, limit = 5 }: MemoryOptions) => {
- const finalUserId = userId || getDefaultUserId(plugin);
- const res = await client.post(`/memories/recent`, {
- userId: finalUserId,
- limit,
- });
- return res.data.results || [];
- };
- };
|