@astramindapp/openclaw-mind 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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/mind-client.ts","../src/config.ts","../src/tools/search.ts","../src/tools/add.ts","../src/tools/get.ts","../src/tools/list.ts","../src/tools/update.ts","../src/tools/delete.ts","../src/tools/query-graph.ts","../src/tools/recall-emotional.ts","../src/tools/context.ts","../src/tools/life.ts","../src/tools/crm-log.ts","../src/tools/index.ts","../src/cli/auth-file.ts","../src/cli/init.ts","../src/cli/status.ts","../src/cli/import.ts","../src/cli/search.ts","../src/cli/index.ts","../src/lib/session.ts","../src/lib/filter.ts","../src/hooks/index.ts"],"sourcesContent":["/**\n * @astramindapp/openclaw-mind\n *\n * MIND personal knowledge graph for OpenClaw.\n * 11 tools, 4 skills, full lifecycle hooks.\n *\n * Pattern modeled on @mem0/openclaw-mem0 (Apache-2.0). Differences:\n * - True knowledge graph backend (LightRAG) instead of vectors\n * - MINDsense emotional weighting on every captured fact (patented)\n * - 11 tools vs Mem0's 8 (adds query_graph, recall_emotional, context, life, crm_log)\n * - 4 skills vs Mem0's 2 (adds emotional-encoding, graph-recall)\n * - Backed by the MIND personal AI platform with 50+ models, life mgmt, CRM, social\n */\n\nimport { definePluginEntry } from \"openclaw/plugin-sdk/plugin-entry\";\nimport { MindClient } from \"./mind-client.js\";\nimport { resolveConfig, type MindPluginConfig, type RawPluginConfig } from \"./config.js\";\nimport { registerAllTools } from \"./tools/index.js\";\nimport { registerCliCommands } from \"./cli/index.js\";\nimport { registerLifecycleHooks } from \"./hooks/index.js\";\n\nconst SETUP_MESSAGE = [\n \"openclaw-mind: MIND_API_KEY not configured. Memory features are disabled.\",\n \" To set up:\",\n \" 1. Get a key at https://www.m-i-n-d.ai → Settings → Developer\",\n \" 2. Run: openclaw mind init --api-key mind_your_key_here\",\n \" Or set MIND_API_KEY in your environment.\",\n].join(\"\\n\");\n\nexport default definePluginEntry({\n id: \"openclaw-mind\",\n name: \"MIND\",\n description:\n \"MIND personal knowledge graph for OpenClaw — true KG, 50+ AI models, MINDsense emotional intelligence, life management, CRM. The most complete memory plugin for AI agents.\",\n kind: \"memory\",\n\n register(api) {\n // 1. Resolve config from plugin settings + env vars\n const cfg: MindPluginConfig = resolveConfig(api.pluginConfig as RawPluginConfig | undefined);\n\n // 2. Bail gracefully if not configured — register CLI so user can run init\n if (cfg.needsSetup) {\n api.logger.warn(SETUP_MESSAGE);\n registerCliCommands(api, null, cfg);\n api.registerService({\n id: \"openclaw-mind\",\n start: () => {\n api.logger.info(\"openclaw-mind: waiting for API key configuration\");\n },\n });\n return;\n }\n\n // 3. Build the MIND HTTP client\n const client = new MindClient({\n apiKey: cfg.apiKey!,\n baseUrl: cfg.baseUrl,\n logger: api.logger,\n });\n\n // 4. Register all 11 tools\n registerAllTools(api, client, cfg);\n\n // 5. Register CLI subcommands (init, status, import, search)\n registerCliCommands(api, client, cfg);\n\n // 6. Register lifecycle hooks (auto-recall + auto-capture)\n if (cfg.autoRecall || cfg.autoCapture) {\n registerLifecycleHooks(api, client, cfg);\n }\n\n // 7. Register a service so other plugins can reach the MIND client\n api.registerService({\n id: \"openclaw-mind\",\n start: () => {\n api.logger.info(\n `openclaw-mind v0.1.0 ready — autoRecall=${cfg.autoRecall} autoCapture=${cfg.autoCapture} baseUrl=${cfg.baseUrl}`,\n );\n },\n });\n },\n});\n","/**\n * MindClient — HTTP client wrapper for the MIND developer API.\n *\n * Auth: X-API-Key header with a `mind_` prefixed key.\n * Base URL: https://www.m-i-n-d.ai (or override for self-hosted).\n *\n * All methods are typed end to end. Errors are normalized to MindClientError\n * with status code, response body, and request context.\n */\n\nexport interface Logger {\n info: (msg: string, ...args: unknown[]) => void;\n warn: (msg: string, ...args: unknown[]) => void;\n error: (msg: string, ...args: unknown[]) => void;\n debug?: (msg: string, ...args: unknown[]) => void;\n}\n\nexport interface MindClientOptions {\n apiKey: string;\n baseUrl?: string;\n logger?: Logger;\n timeoutMs?: number;\n maxRetries?: number;\n}\n\nexport class MindClientError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly path: string,\n public readonly body?: unknown,\n ) {\n super(message);\n this.name = \"MindClientError\";\n }\n}\n\n// ─── Domain types (mirror MIND backend response shapes) ───\n\nexport type QueryMode = \"hybrid\" | \"mix\" | \"global\" | \"local\" | \"naive\";\n\nexport interface QueryRequest {\n query: string;\n mode?: QueryMode;\n top_k?: number;\n history_turns?: number;\n user_prompt?: string;\n}\n\nexport interface QueryResponse {\n answer: string;\n sources?: Array<{\n id: string;\n title?: string;\n snippet?: string;\n score?: number;\n }>;\n credit_cost?: number;\n model_used?: string;\n}\n\nexport interface DocumentCreateRequest {\n title: string;\n content: string;\n tags?: string[];\n source?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface MindDocument {\n id: string;\n title: string;\n content?: string;\n tags?: string[];\n source?: string;\n status?: string;\n created_at?: string;\n updated_at?: string;\n content_preview?: string;\n}\n\nexport interface DocumentListResponse {\n documents: MindDocument[];\n total?: number;\n page?: number;\n page_size?: number;\n}\n\nexport interface EntryCreateRequest {\n title?: string;\n content: string;\n type?: \"thought\" | \"entry\" | \"observation\";\n tags?: string[];\n source?: string;\n}\n\nexport interface MindEntry {\n id: string;\n title?: string;\n content: string;\n type?: string;\n tags?: string[];\n created_at?: string;\n}\n\nexport interface GraphInfoResponse {\n entity_count?: number;\n relationship_count?: number;\n storage_health?: string;\n credits_remaining?: number;\n [key: string]: unknown;\n}\n\nexport interface LifeItemCreateRequest {\n title: string;\n description?: string;\n type?: \"task\" | \"goal\" | \"project\";\n status?: \"todo\" | \"in_progress\" | \"blocked\" | \"done\";\n priority?: \"low\" | \"medium\" | \"high\" | \"urgent\";\n due_date?: string;\n parent_id?: string;\n tags?: string[];\n}\n\nexport interface LifeItem {\n id: string;\n title: string;\n description?: string;\n type?: string;\n status?: string;\n priority?: string;\n due_date?: string;\n created_at?: string;\n}\n\nexport interface CrmContactCreateRequest {\n name: string;\n email?: string;\n phone?: string;\n company?: string;\n type?: string;\n stage?: string;\n notes?: string;\n tags?: string[];\n}\n\nexport interface CrmContact {\n id: string;\n name: string;\n email?: string;\n company?: string;\n stage?: string;\n created_at?: string;\n}\n\nexport interface CrmActivityLogRequest {\n type: \"call\" | \"email\" | \"meeting\" | \"note\" | \"other\";\n summary: string;\n occurred_at?: string;\n metadata?: Record<string, unknown>;\n}\n\n// ─── Client ───\n\nexport class MindClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly logger: Logger | undefined;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n\n constructor(opts: MindClientOptions) {\n if (!opts.apiKey) {\n throw new Error(\"MindClient: apiKey is required\");\n }\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? \"https://www.m-i-n-d.ai\").replace(/\\/$/, \"\");\n this.logger = opts.logger;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n this.maxRetries = opts.maxRetries ?? 2;\n }\n\n // ─── Query / Search ───\n\n async query(req: QueryRequest): Promise<QueryResponse> {\n return this.request<QueryResponse>(\"POST\", \"/developer/v1/query\", req);\n }\n\n // ─── Documents ───\n\n async createDocument(req: DocumentCreateRequest): Promise<MindDocument> {\n return this.request<MindDocument>(\"POST\", \"/developer/v1/documents\", req);\n }\n\n async listDocuments(opts: { limit?: number; offset?: number } = {}): Promise<DocumentListResponse> {\n const params = new URLSearchParams();\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.offset !== undefined) params.set(\"offset\", String(opts.offset));\n const qs = params.toString();\n return this.request<DocumentListResponse>(\n \"GET\",\n `/developer/v1/documents${qs ? `?${qs}` : \"\"}`,\n );\n }\n\n async getDocument(id: string): Promise<MindDocument> {\n return this.request<MindDocument>(\"GET\", `/developer/v1/documents/${id}`);\n }\n\n async deleteDocument(id: string): Promise<{ ok: boolean }> {\n return this.request<{ ok: boolean }>(\"DELETE\", `/developer/v1/documents/${id}`);\n }\n\n // ─── Entries (lighter-weight than documents) ───\n\n async createEntry(req: EntryCreateRequest): Promise<MindEntry> {\n return this.request<MindEntry>(\"POST\", \"/developer/v1/entries\", req);\n }\n\n async listEntries(opts: { limit?: number; offset?: number } = {}): Promise<{ entries: MindEntry[] }> {\n const params = new URLSearchParams();\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.offset !== undefined) params.set(\"offset\", String(opts.offset));\n const qs = params.toString();\n return this.request<{ entries: MindEntry[] }>(\n \"GET\",\n `/developer/v1/entries${qs ? `?${qs}` : \"\"}`,\n );\n }\n\n async searchEntries(query: string, limit = 10): Promise<{ entries: MindEntry[] }> {\n const params = new URLSearchParams({ q: query, limit: String(limit) });\n return this.request<{ entries: MindEntry[] }>(\n \"GET\",\n `/developer/v1/entries/search?${params}`,\n );\n }\n\n async deleteEntry(id: string): Promise<{ ok: boolean }> {\n return this.request<{ ok: boolean }>(\"DELETE\", `/developer/v1/entries/${id}`);\n }\n\n // ─── Graph ───\n\n async getGraphInfo(): Promise<GraphInfoResponse> {\n return this.request<GraphInfoResponse>(\"GET\", \"/developer/v1/graph\");\n }\n\n async getGraphDiagnostics(): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"GET\", \"/developer/v1/graph/diagnostics\");\n }\n\n // ─── Life Management ───\n\n async createLifeItem(req: LifeItemCreateRequest): Promise<LifeItem> {\n return this.request<LifeItem>(\"POST\", \"/developer/v1/life/items\", req);\n }\n\n async listLifeItems(opts: { status?: string; limit?: number } = {}): Promise<{ items: LifeItem[] }> {\n const params = new URLSearchParams();\n if (opts.status) params.set(\"status\", opts.status);\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n const qs = params.toString();\n return this.request<{ items: LifeItem[] }>(\n \"GET\",\n `/developer/v1/life/items${qs ? `?${qs}` : \"\"}`,\n );\n }\n\n async completeLifeItem(id: string): Promise<{ ok: boolean }> {\n return this.request<{ ok: boolean }>(\"POST\", `/developer/v1/life/items/${id}/complete`, {});\n }\n\n // ─── CRM ───\n\n async createCrmContact(req: CrmContactCreateRequest): Promise<CrmContact> {\n return this.request<CrmContact>(\"POST\", \"/developer/v1/crm/contacts\", req);\n }\n\n async listCrmContacts(opts: { limit?: number } = {}): Promise<{ contacts: CrmContact[] }> {\n const params = new URLSearchParams();\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n const qs = params.toString();\n return this.request<{ contacts: CrmContact[] }>(\n \"GET\",\n `/developer/v1/crm/contacts${qs ? `?${qs}` : \"\"}`,\n );\n }\n\n async logCrmActivity(\n contactId: string,\n req: CrmActivityLogRequest,\n ): Promise<{ ok: boolean }> {\n return this.request<{ ok: boolean }>(\n \"POST\",\n `/developer/v1/crm/contacts/${contactId}/activities`,\n req,\n );\n }\n\n // ─── Internal HTTP layer ───\n\n private async request<T>(\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\",\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const headers: Record<string, string> = {\n \"X-API-Key\": this.apiKey,\n Accept: \"application/json\",\n \"User-Agent\": \"openclaw-mind/0.1.0\",\n };\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n let lastError: Error | undefined;\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const resp = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n clearTimeout(timeout);\n\n if (!resp.ok) {\n const text = await resp.text().catch(() => \"\");\n let parsed: unknown = text;\n try {\n parsed = JSON.parse(text);\n } catch {\n // body is not JSON; keep as text\n }\n\n // Retry transient failures\n if ([429, 500, 502, 503, 504].includes(resp.status) && attempt < this.maxRetries) {\n const backoff = 500 * Math.pow(2, attempt);\n this.logger?.warn?.(\n `MIND ${method} ${path} → ${resp.status}, retrying in ${backoff}ms (attempt ${attempt + 1}/${this.maxRetries + 1})`,\n );\n await sleep(backoff);\n continue;\n }\n\n throw new MindClientError(\n `MIND API ${resp.status} ${resp.statusText} on ${method} ${path}`,\n resp.status,\n path,\n parsed,\n );\n }\n\n const ct = resp.headers.get(\"content-type\") ?? \"\";\n if (ct.includes(\"application/json\")) {\n return (await resp.json()) as T;\n }\n return (await resp.text()) as unknown as T;\n } catch (err) {\n clearTimeout(timeout);\n lastError = err as Error;\n if (err instanceof MindClientError) throw err;\n if (attempt < this.maxRetries) {\n const backoff = 500 * Math.pow(2, attempt);\n this.logger?.warn?.(\n `MIND ${method} ${path} network error, retrying in ${backoff}ms: ${(err as Error).message}`,\n );\n await sleep(backoff);\n continue;\n }\n throw err;\n }\n }\n throw lastError ?? new Error(\"MindClient: exhausted retries\");\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * Config resolution for openclaw-mind.\n *\n * Priority (highest first):\n * 1. Plugin config (passed by OpenClaw from openclaw-mind.yaml)\n * 2. Environment variables (MIND_API_KEY, MIND_BASE_URL)\n * 3. Defaults\n */\n\nexport const DEFAULT_BASE_URL = \"https://www.m-i-n-d.ai\";\nexport const DEFAULT_TOP_K = 10;\nexport const DEFAULT_SEARCH_THRESHOLD = 0.5;\nexport const DEFAULT_QUERY_MODE = \"hybrid\" as const;\n\nexport type QueryMode = \"hybrid\" | \"mix\" | \"global\" | \"local\" | \"naive\";\n\nexport interface SkillsConfig {\n triage?: {\n enabled?: boolean;\n importanceThreshold?: number;\n credentialPatterns?: string[];\n };\n recall?: {\n enabled?: boolean;\n strategy?: \"always\" | \"smart\" | \"manual\";\n tokenBudget?: number;\n maxMemories?: number;\n };\n dream?: {\n enabled?: boolean;\n auto?: boolean;\n minHours?: number;\n minSessions?: number;\n };\n emotionalEncoding?: {\n enabled?: boolean;\n minValence?: number;\n minArousal?: number;\n };\n}\n\nexport interface MindPluginConfig {\n apiKey?: string;\n baseUrl: string;\n userId?: string;\n autoCapture: boolean;\n autoRecall: boolean;\n topK: number;\n searchThreshold: number;\n queryMode: QueryMode;\n enableMindsense: boolean;\n enableLifeIntegration: boolean;\n enableCrmLogging: boolean;\n skills?: SkillsConfig;\n needsSetup: boolean;\n}\n\nexport interface RawPluginConfig {\n apiKey?: string;\n baseUrl?: string;\n userId?: string;\n autoCapture?: boolean;\n autoRecall?: boolean;\n topK?: number;\n searchThreshold?: number;\n queryMode?: QueryMode;\n enableMindsense?: boolean;\n enableLifeIntegration?: boolean;\n enableCrmLogging?: boolean;\n skills?: SkillsConfig;\n}\n\nexport function resolveConfig(raw: RawPluginConfig | undefined): MindPluginConfig {\n const apiKey =\n raw?.apiKey ?? process.env.MIND_API_KEY ?? process.env.MINDAPP_API_KEY;\n const baseUrl =\n raw?.baseUrl ?? process.env.MIND_BASE_URL ?? DEFAULT_BASE_URL;\n\n return {\n apiKey,\n baseUrl,\n userId: raw?.userId ?? process.env.MIND_USER_ID,\n autoCapture: raw?.autoCapture ?? true,\n autoRecall: raw?.autoRecall ?? true,\n topK: raw?.topK ?? DEFAULT_TOP_K,\n searchThreshold: raw?.searchThreshold ?? DEFAULT_SEARCH_THRESHOLD,\n queryMode: raw?.queryMode ?? DEFAULT_QUERY_MODE,\n enableMindsense: raw?.enableMindsense ?? true,\n enableLifeIntegration: raw?.enableLifeIntegration ?? true,\n enableCrmLogging: raw?.enableCrmLogging ?? true,\n skills: raw?.skills,\n needsSetup: !apiKey,\n };\n}\n","/**\n * mind_search — Hybrid semantic + knowledge graph search.\n *\n * Wraps POST /developer/v1/query. Uses MIND's LightRAG hybrid mode by default,\n * which blends vector similarity AND graph traversal. Beats pure-vector tools\n * like Mem0 because it surfaces related entities, not just textually similar\n * memories.\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst SearchParameters = Type.Object({\n query: Type.String({ description: \"What to search for\" }),\n mode: Type.Optional(\n Type.Union(\n [\n Type.Literal(\"hybrid\"),\n Type.Literal(\"mix\"),\n Type.Literal(\"global\"),\n Type.Literal(\"local\"),\n Type.Literal(\"naive\"),\n ],\n {\n description:\n \"Query mode. 'hybrid' (default) blends vector + graph. 'global' synthesizes across the full graph. 'local' is entity-focused.\",\n },\n ),\n ),\n top_k: Type.Optional(\n Type.Number({\n description: \"Maximum number of memories to return. Default: 10\",\n minimum: 1,\n maximum: 100,\n }),\n ),\n});\n\ntype SearchParams = Static<typeof SearchParameters>;\n\nexport function createMindSearchTool(deps: ToolDeps) {\n return {\n name: \"mind_search\",\n label: \"MIND Search\",\n description:\n \"Search the MIND knowledge graph using hybrid semantic + graph queries. Returns an AI-synthesized answer grounded in stored memories. Use this whenever the agent needs prior context, decisions, preferences, or facts about the user. MIND's true KG beats vector-only tools because it follows entity relationships, not just text similarity.\",\n parameters: SearchParameters,\n async execute(_toolCallId: string, params: SearchParams) {\n try {\n const result = await deps.client.query({\n query: params.query,\n mode: params.mode ?? deps.config.queryMode,\n top_k: params.top_k ?? deps.config.topK,\n });\n\n const sources = result.sources ?? [];\n const sourceList =\n sources.length > 0\n ? `\\n\\nSources:\\n${sources\n .slice(0, 5)\n .map((s, i) => `${i + 1}. ${s.title ?? \"(untitled)\"}`)\n .join(\"\\n\")}`\n : \"\";\n\n return {\n content: [{ type: \"text\" as const, text: `${result.answer}${sourceList}` }],\n details: {\n answer: result.answer,\n sources,\n model_used: result.model_used,\n },\n };\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `MIND search failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * mind_add — Store a memory in the MIND knowledge graph.\n *\n * Unlike Mem0 which stores text, this auto-extracts entities + relationships +\n * (if MINDsense enabled) emotional valence/arousal weights.\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst AddParameters = Type.Object({\n content: Type.String({\n description: \"The fact or memory to store. Any length — short thoughts to multi-paragraph documents.\",\n }),\n title: Type.Optional(\n Type.String({ description: \"Optional title. Auto-generated from content if omitted.\" }),\n ),\n type: Type.Optional(\n Type.Union(\n [Type.Literal(\"document\"), Type.Literal(\"entry\"), Type.Literal(\"thought\")],\n {\n description:\n \"Storage type. 'document' (long-form), 'entry' (medium), 'thought' (quick). Default: auto-decide by content length.\",\n },\n ),\n ),\n tags: Type.Optional(\n Type.Array(Type.String(), { description: \"Optional tags for retrieval.\" }),\n ),\n});\n\ntype AddParams = Static<typeof AddParameters>;\n\nexport function createMindAddTool(deps: ToolDeps) {\n return {\n name: \"mind_add\",\n label: \"MIND Add Memory\",\n description:\n \"Store a memory in the MIND knowledge graph. Auto-extracts entities (people, places, concepts, events) and the relationships between them. If MINDsense is enabled, also assigns valence/arousal emotional weights that determine encoding depth — emotionally significant content is encoded more deeply, mirroring biological memory consolidation.\",\n parameters: AddParameters,\n async execute(_toolCallId: string, params: AddParams) {\n try {\n const type = params.type ?? autoDecideType(params.content);\n const title = params.title ?? deriveTitle(params.content);\n\n if (type === \"document\") {\n const doc = await deps.client.createDocument({\n title,\n content: params.content,\n tags: params.tags,\n source: \"openclaw-mind\",\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Stored as document \"${doc.title}\" (id: ${doc.id})`,\n },\n ],\n details: { id: doc.id, type: \"document\", title: doc.title },\n };\n }\n\n const entry = await deps.client.createEntry({\n title,\n content: params.content,\n type: type === \"thought\" ? \"thought\" : \"entry\",\n tags: params.tags,\n source: \"openclaw-mind\",\n });\n return {\n content: [\n { type: \"text\" as const, text: `Stored as ${type} \"${entry.title ?? title}\" (id: ${entry.id})` },\n ],\n details: { id: entry.id, type, title: entry.title ?? title },\n };\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_add failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n\nfunction autoDecideType(content: string): \"document\" | \"entry\" | \"thought\" {\n const words = content.trim().split(/\\s+/).length;\n if (words >= 200) return \"document\";\n if (words >= 30) return \"entry\";\n return \"thought\";\n}\n\nfunction deriveTitle(content: string): string {\n const firstLine = content.trim().split(\"\\n\")[0] ?? content;\n return firstLine.slice(0, 100).trim() || \"Untitled memory\";\n}\n","/**\n * mind_get — Retrieve a single memory by ID.\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst GetParameters = Type.Object({\n id: Type.String({ description: \"The memory ID to retrieve\" }),\n type: Type.Optional(\n Type.Union(\n [Type.Literal(\"document\"), Type.Literal(\"entry\")],\n { description: \"Storage type. Default: 'document'\" },\n ),\n ),\n});\n\ntype GetParams = Static<typeof GetParameters>;\n\nexport function createMindGetTool(deps: ToolDeps) {\n return {\n name: \"mind_get\",\n label: \"MIND Get Memory\",\n description: \"Retrieve a single memory by its ID. Returns full content, metadata, tags, timestamps.\",\n parameters: GetParameters,\n async execute(_toolCallId: string, params: GetParams) {\n try {\n const type = params.type ?? \"document\";\n let result: unknown;\n if (type === \"document\") {\n result = await deps.client.getDocument(params.id);\n } else {\n const list = await deps.client.listEntries({ limit: 100 });\n result = list.entries.find((e) => e.id === params.id);\n if (!result) {\n return {\n content: [{ type: \"text\" as const, text: `Entry ${params.id} not found` }],\n details: { error: \"not_found\" },\n };\n }\n }\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n details: result,\n };\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_get failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * mind_list — Paginated list of stored memories.\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst ListParameters = Type.Object({\n type: Type.Optional(\n Type.Union(\n [Type.Literal(\"document\"), Type.Literal(\"entry\"), Type.Literal(\"all\")],\n { description: \"Filter by storage type. Default: 'all'\" },\n ),\n ),\n limit: Type.Optional(\n Type.Number({ description: \"Maximum number to return. Default: 20\", minimum: 1, maximum: 100 }),\n ),\n offset: Type.Optional(Type.Number({ description: \"Pagination offset. Default: 0\", minimum: 0 })),\n});\n\ntype ListParams = Static<typeof ListParameters>;\n\nexport function createMindListTool(deps: ToolDeps) {\n return {\n name: \"mind_list\",\n label: \"MIND List\",\n description:\n \"List stored memories with pagination. Returns IDs, titles, types, tags, timestamps. Use for browsing or when the agent needs to enumerate before deciding what to retrieve.\",\n parameters: ListParameters,\n async execute(_toolCallId: string, params: ListParams) {\n try {\n const limit = params.limit ?? 20;\n const offset = params.offset ?? 0;\n const type = params.type ?? \"all\";\n const result: { documents?: unknown[]; entries?: unknown[] } = {};\n\n if (type === \"document\" || type === \"all\") {\n const docs = await deps.client.listDocuments({ limit, offset });\n result.documents = docs.documents;\n }\n if (type === \"entry\" || type === \"all\") {\n const entries = await deps.client.listEntries({ limit, offset });\n result.entries = entries.entries;\n }\n\n const summary = [\n `${result.documents?.length ?? 0} documents`,\n `${result.entries?.length ?? 0} entries`,\n ].join(\", \");\n\n return {\n content: [{ type: \"text\" as const, text: `${summary}\\n\\n${JSON.stringify(result, null, 2)}` }],\n details: result,\n };\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_list failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * mind_update — Update an existing memory via delete + recreate (preserves KG).\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst UpdateParameters = Type.Object({\n id: Type.String({ description: \"The memory ID to update\" }),\n content: Type.String({ description: \"New content. Replaces the existing content.\" }),\n title: Type.Optional(Type.String({ description: \"New title.\" })),\n tags: Type.Optional(Type.Array(Type.String())),\n type: Type.Optional(\n Type.Union(\n [Type.Literal(\"document\"), Type.Literal(\"entry\")],\n { description: \"Storage type. Default: 'document'\" },\n ),\n ),\n});\n\ntype UpdateParams = Static<typeof UpdateParameters>;\n\nexport function createMindUpdateTool(deps: ToolDeps) {\n return {\n name: \"mind_update\",\n label: \"MIND Update Memory\",\n description:\n \"Update an existing memory's content, title, or tags. The KG is re-extracted from the new content automatically. Use when a stored fact has changed (e.g., user's role, deadline shift, decision update).\",\n parameters: UpdateParameters,\n async execute(_toolCallId: string, params: UpdateParams) {\n try {\n const type = params.type ?? \"document\";\n\n if (type === \"document\") {\n const original = await deps.client.getDocument(params.id);\n await deps.client.deleteDocument(params.id);\n const created = await deps.client.createDocument({\n title: params.title ?? original.title,\n content: params.content,\n tags: params.tags ?? original.tags,\n source: \"openclaw-mind\",\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Updated memory. New id: ${created.id} (was: ${params.id})`,\n },\n ],\n details: { id: created.id, previous_id: params.id, title: created.title },\n };\n }\n\n await deps.client.deleteEntry(params.id);\n const entry = await deps.client.createEntry({\n title: params.title,\n content: params.content,\n type: \"entry\",\n tags: params.tags,\n source: \"openclaw-mind\",\n });\n return {\n content: [\n { type: \"text\" as const, text: `Updated entry. New id: ${entry.id} (was: ${params.id})` },\n ],\n details: { id: entry.id, previous_id: params.id, title: entry.title },\n };\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_update failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * mind_delete — Delete a memory by ID.\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst DeleteParameters = Type.Object({\n id: Type.String({ description: \"The memory ID to delete\" }),\n type: Type.Optional(\n Type.Union(\n [Type.Literal(\"document\"), Type.Literal(\"entry\")],\n { description: \"Storage type. Default: 'document'\" },\n ),\n ),\n});\n\ntype DeleteParams = Static<typeof DeleteParameters>;\n\nexport function createMindDeleteTool(deps: ToolDeps) {\n return {\n name: \"mind_delete\",\n label: \"MIND Delete Memory\",\n description:\n \"Delete a memory by its ID. KG entities and relationships sourced from this memory are removed. Use sparingly — prefer mind_update if content is just changing.\",\n parameters: DeleteParameters,\n async execute(_toolCallId: string, params: DeleteParams) {\n try {\n const type = params.type ?? \"document\";\n if (type === \"document\") {\n await deps.client.deleteDocument(params.id);\n } else {\n await deps.client.deleteEntry(params.id);\n }\n return {\n content: [{ type: \"text\" as const, text: `Deleted ${type} ${params.id}` }],\n details: { id: params.id, status: \"deleted\" },\n };\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_delete failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * mind_query_graph — UNIQUE TO MIND\n *\n * Graph traversal queries over the MIND knowledge graph. Vector-only memory\n * tools cannot do this — they only do similarity search. MIND has a real KG\n * (LightRAG) so the agent can ask graph-shaped questions like \"who is connected\n * to X\" or \"what concepts cluster around Y\".\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst QueryGraphParameters = Type.Object({\n question: Type.String({\n description:\n \"A graph-shaped question. Examples: 'Who is connected to Sarah?', 'What concepts cluster around the KGC pitch?', 'What decisions are linked to the auth migration?'\",\n }),\n mode: Type.Optional(\n Type.Union([Type.Literal(\"global\"), Type.Literal(\"local\"), Type.Literal(\"mix\")], {\n description:\n \"Graph query mode. 'global' (default) synthesizes across the full graph. 'local' is entity-focused. 'mix' balances both.\",\n }),\n ),\n});\n\ntype QueryGraphParams = Static<typeof QueryGraphParameters>;\n\nexport function createMindQueryGraphTool(deps: ToolDeps) {\n return {\n name: \"mind_query_graph\",\n label: \"MIND Graph Query\",\n description:\n \"Query the MIND knowledge graph by structure, not just similarity. Use for questions about RELATIONSHIPS between entities. Example: mind_search answers 'what did the user say about Sarah?'; mind_query_graph answers 'who is Sarah connected to and how?'. This is a true KG capability vector-only memory tools cannot match.\",\n parameters: QueryGraphParameters,\n async execute(_toolCallId: string, params: QueryGraphParams) {\n try {\n const result = await deps.client.query({\n query: params.question,\n mode: params.mode ?? \"global\",\n top_k: 30,\n });\n return {\n content: [{ type: \"text\" as const, text: result.answer }],\n details: {\n answer: result.answer,\n sources: result.sources ?? [],\n mode: params.mode ?? \"global\",\n },\n };\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_query_graph failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * mind_recall_emotional — UNIQUE TO MIND (PATENTED via MIND-PAT-001)\n *\n * Emotionally weighted memory recall using MINDsense valence + arousal scores.\n * No other memory tool does this.\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst RecallEmotionalParameters = Type.Object({\n query: Type.String({\n description: \"What to search for, biased toward emotionally salient memories.\",\n }),\n emotion_filter: Type.Optional(\n Type.Union(\n [\n Type.Literal(\"positive\"),\n Type.Literal(\"negative\"),\n Type.Literal(\"high_arousal\"),\n Type.Literal(\"low_arousal\"),\n Type.Literal(\"triumph\"),\n Type.Literal(\"warning\"),\n Type.Literal(\"any\"),\n ],\n {\n description:\n \"Filter by emotional category. 'positive'=high valence. 'negative'=low valence. 'high_arousal'=intense moments. 'triumph' / 'warning' = MINDsense semantic categories.\",\n },\n ),\n ),\n min_intensity: Type.Optional(\n Type.Number({\n description: \"Minimum emotional intensity (0-1). Default: 0.3\",\n minimum: 0,\n maximum: 1,\n }),\n ),\n top_k: Type.Optional(\n Type.Number({ description: \"Maximum results. Default: 10\", minimum: 1, maximum: 50 }),\n ),\n});\n\ntype RecallEmotionalParams = Static<typeof RecallEmotionalParameters>;\n\nexport function createMindRecallEmotionalTool(deps: ToolDeps) {\n return {\n name: \"mind_recall_emotional\",\n label: \"MIND Emotional Recall\",\n description:\n \"Recall memories weighted by emotional significance (MINDsense, patented). Use when the agent needs to understand the user's strong feelings, important moments, frustrations, wins, or warnings. Example queries: 'what frustrates the user about deployment', 'what wins did the user celebrate this month'.\",\n parameters: RecallEmotionalParameters,\n async execute(_toolCallId: string, params: RecallEmotionalParams) {\n try {\n const emotionTag = params.emotion_filter ?? \"any\";\n const intensityHint = params.min_intensity ?? 0.3;\n const augmentedQuery = `${params.query}\\n\\n[Emotional context: ${emotionTag}, min_intensity=${intensityHint}]`;\n\n const result = await deps.client.query({\n query: augmentedQuery,\n mode: \"hybrid\",\n top_k: params.top_k ?? 10,\n });\n\n return {\n content: [{ type: \"text\" as const, text: result.answer }],\n details: {\n answer: result.answer,\n sources: result.sources ?? [],\n emotion_filter: emotionTag,\n min_intensity: intensityHint,\n },\n };\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_recall_emotional failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * mind_context — UNIQUE TO MIND\n *\n * Loads structured persistent context (soul, user, rules, priorities, recent).\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst ContextParameters = Type.Object({\n sections: Type.Optional(\n Type.Array(\n Type.Union([\n Type.Literal(\"soul\"),\n Type.Literal(\"user\"),\n Type.Literal(\"rules\"),\n Type.Literal(\"priorities\"),\n Type.Literal(\"recent\"),\n ]),\n {\n description:\n \"Which context sections to load. Default: all 5. 'soul'=identity. 'user'=preferences. 'rules'=constraints. 'priorities'=current goals. 'recent'=last 7 days.\",\n },\n ),\n ),\n});\n\ntype ContextParams = Static<typeof ContextParameters>;\n\nconst SECTION_QUERIES: Record<string, string> = {\n soul: \"user identity mission personality core values\",\n user: \"user preferences role responsibilities personal details\",\n rules: \"operating rules constraints guardrails behavioral preferences\",\n priorities: \"current priorities goals deadlines active projects this quarter\",\n recent: \"recent activity last 7 days outcomes decisions\",\n};\n\nexport function createMindContextTool(deps: ToolDeps) {\n return {\n name: \"mind_context\",\n label: \"MIND Context\",\n description:\n \"Load structured persistent context at session start. Returns 5 sections: soul, user, rules, priorities, recent. Call FIRST in any session to ground the agent in who the user is and what matters now.\",\n parameters: ContextParameters,\n async execute(_toolCallId: string, params: ContextParams) {\n const sections = params.sections ?? [\"soul\", \"user\", \"rules\", \"priorities\", \"recent\"];\n const result: Record<string, unknown> = {};\n\n await Promise.all(\n sections.map(async (section) => {\n const queryStr = SECTION_QUERIES[section] ?? section;\n try {\n const resp = await deps.client.query({\n query: queryStr,\n mode: \"hybrid\",\n top_k: 8,\n });\n result[section] = {\n summary: resp.answer,\n sources: (resp.sources ?? []).slice(0, 5),\n };\n } catch (err) {\n result[section] = { error: (err as Error).message };\n }\n }),\n );\n\n const summary = sections\n .map((s) => {\n const sec = result[s] as { summary?: string; error?: string };\n if (sec?.error) return `## ${s.toUpperCase()}\\n[Error: ${sec.error}]`;\n return `## ${s.toUpperCase()}\\n${sec?.summary ?? \"\"}`;\n })\n .join(\"\\n\\n\");\n\n return {\n content: [{ type: \"text\" as const, text: summary }],\n details: result,\n };\n },\n };\n}\n","/**\n * mind_life — UNIQUE TO MIND\n *\n * Life management: tasks, goals, projects, calendar events.\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst LifeParameters = Type.Object({\n action: Type.Union(\n [Type.Literal(\"create\"), Type.Literal(\"list\"), Type.Literal(\"complete\")],\n { description: \"What to do\" },\n ),\n title: Type.Optional(Type.String({ description: \"Item title (required for create)\" })),\n description: Type.Optional(Type.String()),\n type: Type.Optional(\n Type.Union(\n [Type.Literal(\"task\"), Type.Literal(\"goal\"), Type.Literal(\"project\")],\n { description: \"Item type. Default: 'task'\" },\n ),\n ),\n priority: Type.Optional(\n Type.Union(\n [\n Type.Literal(\"low\"),\n Type.Literal(\"medium\"),\n Type.Literal(\"high\"),\n Type.Literal(\"urgent\"),\n ],\n { description: \"Priority. Default: 'medium'\" },\n ),\n ),\n due_date: Type.Optional(Type.String({ description: \"ISO date or datetime\" })),\n status: Type.Optional(\n Type.Union(\n [\n Type.Literal(\"todo\"),\n Type.Literal(\"in_progress\"),\n Type.Literal(\"blocked\"),\n Type.Literal(\"done\"),\n Type.Literal(\"all\"),\n ],\n { description: \"Filter for list. Default: 'todo'\" },\n ),\n ),\n limit: Type.Optional(Type.Number({ description: \"Max results for list. Default: 20\" })),\n item_id: Type.Optional(Type.String({ description: \"Item ID for complete\" })),\n});\n\ntype LifeParams = Static<typeof LifeParameters>;\n\nexport function createMindLifeTool(deps: ToolDeps) {\n return {\n name: \"mind_life\",\n label: \"MIND Life\",\n description:\n \"Manage MIND Life items (tasks, goals, projects). Use when the user mentions something to do, a deadline, a goal, or a project. Actions: 'create', 'list', 'complete'. MIND Life syncs to web and mobile apps.\",\n parameters: LifeParameters,\n async execute(_toolCallId: string, params: LifeParams) {\n try {\n switch (params.action) {\n case \"create\": {\n if (!params.title) {\n return {\n content: [{ type: \"text\" as const, text: \"'title' is required for action='create'\" }],\n details: { error: \"missing_title\" },\n };\n }\n const item = await deps.client.createLifeItem({\n title: params.title,\n description: params.description,\n type: params.type ?? \"task\",\n status: \"todo\",\n priority: params.priority ?? \"medium\",\n due_date: params.due_date,\n });\n return {\n content: [{ type: \"text\" as const, text: `Created life item \"${item.title}\" (id: ${item.id})` }],\n details: item,\n };\n }\n case \"list\": {\n const status = params.status ?? \"todo\";\n const items = await deps.client.listLifeItems({\n status: status === \"all\" ? undefined : status,\n limit: params.limit ?? 20,\n });\n const list = items.items\n .map((i) => `- [${i.status}] ${i.title} ${i.due_date ? `(due ${i.due_date})` : \"\"}`)\n .join(\"\\n\");\n return {\n content: [{ type: \"text\" as const, text: `${items.items.length} items:\\n${list}` }],\n details: items,\n };\n }\n case \"complete\": {\n if (!params.item_id) {\n return {\n content: [{ type: \"text\" as const, text: \"'item_id' is required for action='complete'\" }],\n details: { error: \"missing_item_id\" },\n };\n }\n await deps.client.completeLifeItem(params.item_id);\n return {\n content: [{ type: \"text\" as const, text: `Completed life item ${params.item_id}` }],\n details: { id: params.item_id, status: \"completed\" },\n };\n }\n }\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_life failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * mind_crm_log — UNIQUE TO MIND\n *\n * CRM activity logging.\n */\n\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport type { ToolDeps } from \"./index.js\";\n\nconst CrmLogParameters = Type.Object({\n action: Type.Union(\n [\n Type.Literal(\"create_contact\"),\n Type.Literal(\"list_contacts\"),\n Type.Literal(\"log_activity\"),\n ],\n { description: \"What to do\" },\n ),\n name: Type.Optional(Type.String({ description: \"Contact name (required for create_contact)\" })),\n email: Type.Optional(Type.String()),\n phone: Type.Optional(Type.String()),\n company: Type.Optional(Type.String()),\n type: Type.Optional(Type.String({ description: \"Relationship type: investor, partner, customer\" })),\n stage: Type.Optional(Type.String({ description: \"Pipeline stage\" })),\n notes: Type.Optional(Type.String()),\n contact_id: Type.Optional(Type.String({ description: \"Contact ID for log_activity\" })),\n activity_type: Type.Optional(\n Type.Union(\n [\n Type.Literal(\"call\"),\n Type.Literal(\"email\"),\n Type.Literal(\"meeting\"),\n Type.Literal(\"note\"),\n Type.Literal(\"other\"),\n ],\n { description: \"Activity type\" },\n ),\n ),\n summary: Type.Optional(Type.String({ description: \"What happened\" })),\n occurred_at: Type.Optional(Type.String({ description: \"ISO datetime\" })),\n limit: Type.Optional(Type.Number({ description: \"Max contacts to list\" })),\n});\n\ntype CrmLogParams = Static<typeof CrmLogParameters>;\n\nexport function createMindCrmLogTool(deps: ToolDeps) {\n return {\n name: \"mind_crm_log\",\n label: \"MIND CRM\",\n description:\n \"Manage MIND CRM contacts and log interactions. Use when the user mentions a person they're working with, a meeting, an email, or a relationship. Actions: 'create_contact', 'list_contacts', 'log_activity'.\",\n parameters: CrmLogParameters,\n async execute(_toolCallId: string, params: CrmLogParams) {\n try {\n switch (params.action) {\n case \"create_contact\": {\n if (!params.name) {\n return {\n content: [{ type: \"text\" as const, text: \"'name' is required for create_contact\" }],\n details: { error: \"missing_name\" },\n };\n }\n const contact = await deps.client.createCrmContact({\n name: params.name,\n email: params.email,\n phone: params.phone,\n company: params.company,\n type: params.type,\n stage: params.stage,\n notes: params.notes,\n });\n return {\n content: [{ type: \"text\" as const, text: `Created contact ${contact.name} (id: ${contact.id})` }],\n details: contact,\n };\n }\n case \"list_contacts\": {\n const contacts = await deps.client.listCrmContacts({ limit: params.limit ?? 20 });\n const list = contacts.contacts.map((c) => `- ${c.name} ${c.company ? `(${c.company})` : \"\"}`).join(\"\\n\");\n return {\n content: [{ type: \"text\" as const, text: `${contacts.contacts.length} contacts:\\n${list}` }],\n details: contacts,\n };\n }\n case \"log_activity\": {\n if (!params.contact_id || !params.activity_type || !params.summary) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"'contact_id', 'activity_type', and 'summary' are required for log_activity\",\n },\n ],\n details: { error: \"missing_required\" },\n };\n }\n await deps.client.logCrmActivity(params.contact_id, {\n type: params.activity_type,\n summary: params.summary,\n occurred_at: params.occurred_at,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Logged ${params.activity_type} activity for contact ${params.contact_id}`,\n },\n ],\n details: { contact_id: params.contact_id, activity_type: params.activity_type },\n };\n }\n }\n } catch (err) {\n const msg = (err as Error).message;\n return {\n content: [{ type: \"text\" as const, text: `mind_crm_log failed: ${msg}` }],\n details: { error: msg },\n };\n }\n },\n };\n}\n","/**\n * Tool registration entry point.\n *\n * Each tool is defined in its own file and registered here. The pattern mirrors\n * Mem0's openclaw plugin: each `create*Tool` factory takes a deps object\n * (client + config) and returns a tool definition for `api.registerTool`.\n */\n\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { MindClient } from \"../mind-client.js\";\nimport type { MindPluginConfig } from \"../config.js\";\n\nimport { createMindSearchTool } from \"./search.js\";\nimport { createMindAddTool } from \"./add.js\";\nimport { createMindGetTool } from \"./get.js\";\nimport { createMindListTool } from \"./list.js\";\nimport { createMindUpdateTool } from \"./update.js\";\nimport { createMindDeleteTool } from \"./delete.js\";\nimport { createMindQueryGraphTool } from \"./query-graph.js\";\nimport { createMindRecallEmotionalTool } from \"./recall-emotional.js\";\nimport { createMindContextTool } from \"./context.js\";\nimport { createMindLifeTool } from \"./life.js\";\nimport { createMindCrmLogTool } from \"./crm-log.js\";\n\nexport interface ToolDeps {\n client: MindClient;\n config: MindPluginConfig;\n}\n\nexport function registerAllTools(\n api: OpenClawPluginApi,\n client: MindClient,\n config: MindPluginConfig,\n): void {\n const deps: ToolDeps = { client, config };\n\n // Core memory CRUD (parity with Mem0)\n api.registerTool(createMindSearchTool(deps));\n api.registerTool(createMindAddTool(deps));\n api.registerTool(createMindGetTool(deps));\n api.registerTool(createMindListTool(deps));\n api.registerTool(createMindUpdateTool(deps));\n api.registerTool(createMindDeleteTool(deps));\n\n // MIND-unique capabilities\n api.registerTool(createMindQueryGraphTool(deps));\n if (config.enableMindsense) {\n api.registerTool(createMindRecallEmotionalTool(deps));\n }\n api.registerTool(createMindContextTool(deps));\n if (config.enableLifeIntegration) {\n api.registerTool(createMindLifeTool(deps));\n }\n if (config.enableCrmLogging) {\n api.registerTool(createMindCrmLogTool(deps));\n }\n}\n","/**\n * Auth file persistence at ~/.openclaw/plugins/openclaw-mind.json.\n *\n * Stores the user's API key + base URL so they don't need to set env vars.\n * The plugin reads this on startup via the readPluginAuth helper.\n */\n\nimport { promises as fs } from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\nconst AUTH_DIR = path.join(os.homedir(), \".openclaw\", \"plugins\");\nconst AUTH_FILE = path.join(AUTH_DIR, \"openclaw-mind.json\");\n\nexport interface AuthFile {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport async function writeAuthFile(auth: AuthFile): Promise<void> {\n await fs.mkdir(AUTH_DIR, { recursive: true, mode: 0o700 });\n await fs.writeFile(AUTH_FILE, JSON.stringify(auth, null, 2), { mode: 0o600 });\n}\n\nexport async function readAuthFile(): Promise<AuthFile | null> {\n try {\n const text = await fs.readFile(AUTH_FILE, \"utf8\");\n return JSON.parse(text) as AuthFile;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw err;\n }\n}\n","/**\n * `openclaw mind init` — Set up the MIND API key.\n */\n\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { MindPluginConfig } from \"../config.js\";\nimport { MindClient } from \"../mind-client.js\";\nimport { writeAuthFile } from \"./auth-file.js\";\n\ninterface InitOpts {\n apiKey?: string;\n email?: string;\n baseUrl?: string;\n}\n\nexport async function initCommand(\n api: OpenClawPluginApi,\n opts: InitOpts,\n config: MindPluginConfig,\n): Promise<void> {\n const baseUrl = opts.baseUrl ?? config.baseUrl;\n\n if (opts.apiKey) {\n return setupWithApiKey(api, opts.apiKey, baseUrl);\n }\n\n if (opts.email) {\n return setupWithMagicLink(api, opts.email, baseUrl);\n }\n\n api.logger.info(\n [\n \"To set up MIND, provide an API key or email:\",\n \"\",\n \" openclaw mind init --api-key mind_your_key_here\",\n \" openclaw mind init --email you@example.com\",\n \"\",\n \"Get an API key at https://www.m-i-n-d.ai → Settings → Developer → Create API Key\",\n ].join(\"\\n\"),\n );\n}\n\nasync function setupWithApiKey(\n api: OpenClawPluginApi,\n apiKey: string,\n baseUrl: string,\n): Promise<void> {\n if (!apiKey.startsWith(\"mind_\")) {\n api.logger.error(\"Invalid API key format. Keys must start with 'mind_'.\");\n return;\n }\n\n const client = new MindClient({ apiKey, baseUrl, logger: api.logger });\n try {\n const info = await client.getGraphInfo();\n api.logger.info(\n [\n \"✓ Connected to MIND\",\n ` Entities: ${info.entity_count ?? \"?\"}`,\n ` Relationships: ${info.relationship_count ?? \"?\"}`,\n ` Credits remaining: ${info.credits_remaining ?? \"?\"}`,\n ].join(\"\\n\"),\n );\n\n await writeAuthFile({ apiKey, baseUrl });\n api.logger.info(\"✓ API key saved. MIND auto-recall and auto-capture are now active.\");\n } catch (err) {\n api.logger.error(\n `Failed to verify MIND API key: ${(err as Error).message}\\nDouble-check the key at https://www.m-i-n-d.ai/settings/developer`,\n );\n }\n}\n\nasync function setupWithMagicLink(\n api: OpenClawPluginApi,\n _email: string,\n _baseUrl: string,\n): Promise<void> {\n api.logger.error(\n [\n \"Magic-link auth is coming in v0.2. For now, use --api-key:\",\n \"\",\n \" openclaw mind init --api-key mind_your_key_here\",\n \"\",\n \"Get a key at https://www.m-i-n-d.ai → Settings → Developer.\",\n ].join(\"\\n\"),\n );\n}\n","/**\n * `openclaw mind status` — Show MIND connection and account info.\n */\n\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { MindClient } from \"../mind-client.js\";\nimport type { MindPluginConfig } from \"../config.js\";\n\nexport async function statusCommand(\n api: OpenClawPluginApi,\n client: MindClient | null,\n config: MindPluginConfig,\n): Promise<void> {\n if (!client || config.needsSetup) {\n api.logger.info(\n [\n \"MIND: NOT CONNECTED\",\n \"\",\n \"Run: openclaw mind init --api-key mind_your_key_here\",\n \"Get a key at https://www.m-i-n-d.ai → Settings → Developer\",\n ].join(\"\\n\"),\n );\n return;\n }\n\n try {\n const info = await client.getGraphInfo();\n api.logger.info(\n [\n \"MIND: CONNECTED\",\n ` Base URL: ${config.baseUrl}`,\n ` Entities: ${info.entity_count ?? \"?\"}`,\n ` Relationships: ${info.relationship_count ?? \"?\"}`,\n ` Storage health: ${info.storage_health ?? \"?\"}`,\n ` Credits left: ${info.credits_remaining ?? \"?\"}`,\n \"\",\n \"Settings:\",\n ` Auto-recall: ${config.autoRecall}`,\n ` Auto-capture: ${config.autoCapture}`,\n ` Top-K recall: ${config.topK}`,\n ` Query mode: ${config.queryMode}`,\n ` MINDsense: ${config.enableMindsense}`,\n ` Life integration: ${config.enableLifeIntegration}`,\n ` CRM logging: ${config.enableCrmLogging}`,\n ].join(\"\\n\"),\n );\n } catch (err) {\n api.logger.error(`Failed to reach MIND: ${(err as Error).message}`);\n }\n}\n","/**\n * `openclaw mind import` — Migrate OpenClaw workspace memory files into MIND.\n *\n * Reads files from ~/.openclaw/workspace/:\n * - SOUL.md, IDENTITY.md, USER.md, MEMORY.md (if they exist)\n * - memory/YYYY-MM-DD.md files (most recent N days)\n *\n * Skips: AGENTS.md, BOOTSTRAP.md, HEARTBEAT.md, TOOLS.md (operational, not memory).\n *\n * Each file becomes a MIND document, which triggers automatic entity + relationship\n * extraction on the server side. Files >2000 words are split by H1 heading.\n */\n\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { MindClient } from \"../mind-client.js\";\nimport type { MindPluginConfig } from \"../config.js\";\nimport { promises as fs } from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\nconst ALWAYS_IMPORT = [\"SOUL.md\", \"IDENTITY.md\", \"USER.md\", \"MEMORY.md\"];\nconst SKIP = new Set([\"AGENTS.md\", \"BOOTSTRAP.md\", \"HEARTBEAT.md\", \"TOOLS.md\"]);\nconst WORDS_PER_DOCUMENT_THRESHOLD = 2000;\n\ninterface ImportOpts {\n workspace?: string;\n days?: string;\n}\n\nexport async function importCommand(\n api: OpenClawPluginApi,\n client: MindClient | null,\n config: MindPluginConfig,\n opts: ImportOpts,\n): Promise<void> {\n if (!client || config.needsSetup) {\n api.logger.error(\"MIND not configured. Run: openclaw mind init --api-key mind_...\");\n return;\n }\n\n const workspace = opts.workspace ?? path.join(os.homedir(), \".openclaw\", \"workspace\");\n const days = parseInt(opts.days ?? \"30\", 10);\n\n if (!(await pathExists(workspace))) {\n api.logger.error(`Workspace not found: ${workspace}`);\n return;\n }\n\n api.logger.info(`Scanning ${workspace}...`);\n\n const items: Array<{ title: string; content: string; tags: string[] }> = [];\n\n // 1. Always-import top-level files\n for (const filename of ALWAYS_IMPORT) {\n const filepath = path.join(workspace, filename);\n if (await pathExists(filepath)) {\n const content = await fs.readFile(filepath, \"utf8\");\n items.push(...splitFile(filename, content, [\"openclaw-import\", \"core-memory\"]));\n }\n }\n\n // 2. Recent memory dir files\n const memoryDir = path.join(workspace, \"memory\");\n if (await pathExists(memoryDir)) {\n const files = await fs.readdir(memoryDir);\n const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;\n const dateFiles = files\n .filter((f) => /^\\d{4}-\\d{2}-\\d{2}\\.md$/.test(f))\n .sort()\n .reverse();\n\n for (const file of dateFiles) {\n const dateStr = file.replace(\".md\", \"\");\n const fileTime = new Date(dateStr).getTime();\n if (Number.isNaN(fileTime) || fileTime < cutoff) continue;\n\n const filepath = path.join(memoryDir, file);\n const content = await fs.readFile(filepath, \"utf8\");\n items.push(...splitFile(file, content, [\"openclaw-import\", \"daily-memory\", dateStr]));\n }\n }\n\n // 3. Show preview\n if (items.length === 0) {\n api.logger.info(\"Nothing to import.\");\n return;\n }\n\n api.logger.info(`Found ${items.length} memory chunks. Importing to MIND...`);\n\n // 4. Import in series (avoid hammering the API)\n let succeeded = 0;\n let failed = 0;\n for (const item of items) {\n try {\n await client.createDocument({\n title: item.title,\n content: item.content,\n tags: item.tags,\n source: \"openclaw-mind-import\",\n });\n succeeded++;\n } catch (err) {\n failed++;\n api.logger?.warn(`Failed to import \"${item.title}\": ${(err as Error).message}`);\n }\n }\n\n api.logger.info(\n `Done. Imported: ${succeeded}, failed: ${failed}. Run \\`openclaw mind status\\` to see updated entity count.`,\n );\n}\n\nfunction splitFile(\n filename: string,\n content: string,\n tags: string[],\n): Array<{ title: string; content: string; tags: string[] }> {\n if (SKIP.has(filename)) return [];\n const wordCount = content.trim().split(/\\s+/).length;\n if (wordCount <= WORDS_PER_DOCUMENT_THRESHOLD) {\n return [\n {\n title: `${filename}`,\n content: content.trim(),\n tags,\n },\n ];\n }\n\n // Split by H1 headings if file is large\n const sections: Array<{ title: string; content: string; tags: string[] }> = [];\n const lines = content.split(\"\\n\");\n let currentTitle = filename;\n let currentBuffer: string[] = [];\n\n const flush = () => {\n const text = currentBuffer.join(\"\\n\").trim();\n if (text.length > 0) {\n sections.push({ title: currentTitle, content: text, tags });\n }\n };\n\n for (const line of lines) {\n if (line.startsWith(\"# \")) {\n flush();\n currentBuffer = [line];\n currentTitle = `${filename} — ${line.replace(/^#\\s*/, \"\").trim()}`;\n } else {\n currentBuffer.push(line);\n }\n }\n flush();\n\n return sections;\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try {\n await fs.stat(p);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * `openclaw mind search \"query\"` — Quick CLI search of the MIND KG.\n */\n\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { MindClient, QueryMode } from \"../mind-client.js\";\n\ninterface SearchOpts {\n query: string;\n mode?: string;\n topK?: string;\n}\n\nexport async function searchCommand(\n api: OpenClawPluginApi,\n client: MindClient | null,\n opts: SearchOpts,\n): Promise<void> {\n if (!client) {\n api.logger.error(\"MIND not configured. Run: openclaw mind init --api-key mind_...\");\n return;\n }\n\n if (!opts.query) {\n api.logger.error(\"Usage: openclaw mind search \\\"your query\\\"\");\n return;\n }\n\n const mode = (opts.mode ?? \"hybrid\") as QueryMode;\n const topK = parseInt(opts.topK ?? \"5\", 10);\n\n try {\n const result = await client.query({\n query: opts.query,\n mode,\n top_k: topK,\n });\n\n api.logger.info(`\\n${result.answer}\\n`);\n\n if (result.sources && result.sources.length > 0) {\n const sourceLines = result.sources.map((s, i) => {\n const score = s.score ? `(score: ${s.score.toFixed(2)})` : \"\";\n return ` ${i + 1}. ${s.title ?? \"(untitled)\"} ${score}`;\n });\n api.logger.info(`Sources:\\n${sourceLines.join(\"\\n\")}`);\n }\n } catch (err) {\n api.logger.error(`Search failed: ${(err as Error).message}`);\n }\n}\n","/**\n * CLI subcommands for openclaw-mind.\n *\n * Uses OpenClaw's Commander-based registration pattern.\n * openclaw mind init [--api-key KEY]\n * openclaw mind status\n * openclaw mind import [--workspace PATH]\n * openclaw mind search \"query\"\n *\n * The registrar callback receives an `OpenClawPluginCliContext` with a\n * Commander `Command` instance. We use `any` for the parameter and action\n * callbacks because Commander's TypeScript types use overloads our local\n * structural stubs can't match — but the runtime contract is stable.\n */\n\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { MindClient } from \"../mind-client.js\";\nimport type { MindPluginConfig } from \"../config.js\";\nimport { initCommand } from \"./init.js\";\nimport { statusCommand } from \"./status.js\";\nimport { importCommand } from \"./import.js\";\nimport { searchCommand } from \"./search.js\";\n\nexport function registerCliCommands(\n api: OpenClawPluginApi,\n client: MindClient | null,\n config: MindPluginConfig,\n): void {\n api.registerCli(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (ctx: any) => {\n const program = ctx.program;\n const mind = program\n .command(\"mind\")\n .description(\"MIND personal knowledge graph commands\");\n\n mind\n .command(\"init\")\n .description(\"Set up your MIND API key and verify the connection\")\n .option(\"--api-key <key>\", \"MIND API key (mind_...)\")\n .option(\"--email <email>\", \"Email for magic-link auth (alternative to api-key)\")\n .option(\"--base-url <url>\", \"Override the MIND base URL (for self-hosting)\")\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n .action(async (opts: any) => {\n await initCommand(\n api,\n { apiKey: opts.apiKey, email: opts.email, baseUrl: opts.baseUrl },\n config,\n );\n });\n\n mind\n .command(\"status\")\n .description(\"Verify the MIND connection and show your account info\")\n .action(async () => {\n await statusCommand(api, client, config);\n });\n\n mind\n .command(\"import\")\n .description(\"Import OpenClaw workspace memory files into MIND\")\n .option(\n \"--workspace <path>\",\n \"Path to OpenClaw workspace dir (default: ~/.openclaw/workspace)\",\n )\n .option(\"--days <n>\", \"How many days of recent memory files to import (default: 30)\")\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n .action(async (opts: any) => {\n await importCommand(api, client, config, {\n workspace: opts.workspace,\n days: opts.days,\n });\n });\n\n mind\n .command(\"search\")\n .description(\"Quick CLI search of the MIND knowledge graph\")\n .argument(\"<query>\", \"What to search for\")\n .option(\"--mode <mode>\", \"Query mode (hybrid/mix/global/local/naive)\")\n .option(\"--top-k <n>\", \"Max results (default: 5)\")\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n .action(async (query: string, opts: any) => {\n await searchCommand(api, client, {\n query,\n mode: opts.mode,\n topK: opts.topK,\n });\n });\n },\n { commands: [\"mind\"] },\n );\n}\n","/**\n * Session and namespace helpers for per-agent memory isolation.\n *\n * OpenClaw session key formats (mirrors @mem0/openclaw-mem0):\n * - Main agent: \"agent:main:main\"\n * - Subagent: \"agent:main:subagent:<uuid>\"\n * - Named agent: \"agent:<agentId>:<session>\"\n *\n * Subagent UUIDs are random per-spawn, so their namespaces are always empty\n * on recall and orphaned after capture. We skip both hooks for subagents.\n */\n\nconst NON_INTERACTIVE_TRIGGERS = new Set([\"cron\", \"scheduled\", \"webhook\", \"event\", \"system\"]);\nconst SUBAGENT_PATTERN = /:subagent:/;\nconst CRON_SESSION_PATTERN = /:cron:/;\n\nexport function isNonInteractiveTrigger(\n trigger: string | undefined,\n sessionKey: string | undefined,\n): boolean {\n if (trigger && NON_INTERACTIVE_TRIGGERS.has(trigger.toLowerCase())) {\n return true;\n }\n if (sessionKey && CRON_SESSION_PATTERN.test(sessionKey)) {\n return true;\n }\n return false;\n}\n\nexport function isSubagentSession(sessionKey: string | undefined): boolean {\n if (!sessionKey) return false;\n return SUBAGENT_PATTERN.test(sessionKey);\n}\n\nexport function extractAgentId(sessionKey: string | undefined): string | undefined {\n if (!sessionKey) return undefined;\n const parts = sessionKey.split(\":\");\n // \"agent:main:subagent:<uuid>\" → return uuid\n if (parts[0] === \"agent\" && parts[1] === \"main\" && parts[2] === \"subagent\" && parts[3]) {\n return parts[3];\n }\n // \"agent:<agentId>:<session>\" — non-main named agent\n if (parts[0] === \"agent\" && parts[1] && parts[1] !== \"main\") {\n return parts[1];\n }\n return undefined;\n}\n\nexport function effectiveUserId(baseUserId: string, sessionKey?: string): string {\n const agentId = extractAgentId(sessionKey);\n if (!agentId) return baseUserId;\n return `${baseUserId}:${agentId}`;\n}\n","/**\n * Pre-extraction message filtering: noise detection, content stripping,\n * generic assistant detection, deduplication.\n *\n * Mirrors the filtering in @mem0/openclaw-mem0 to ensure auto-capture\n * doesn't store cron heartbeats, single-word acknowledgments, or system\n * routing metadata in the MIND knowledge graph.\n */\n\ninterface Message {\n role: string;\n content: string;\n}\n\nconst NOISE_PATTERNS = [\n /^heartbeat\\b/i,\n /^cron:/i,\n /^ping$/i,\n /^pong$/i,\n /^ok$/i,\n /^thanks$/i,\n /^thank you$/i,\n /^got it$/i,\n /^sure$/i,\n /^yes$/i,\n /^no$/i,\n];\n\nconst GENERIC_ASSISTANT_PATTERNS = [\n /^how can i (help|assist) you/i,\n /^what (can|would you like)/i,\n /^i('m| am) (here to help|happy to help)/i,\n /^sure[,.!]? (i can|let me)/i,\n /^certainly[,.!]/i,\n];\n\nconst NOISE_FRAGMENTS = [\n /<routing-metadata>[\\s\\S]*?<\\/routing-metadata>/g,\n /<compaction-audit>[\\s\\S]*?<\\/compaction-audit>/g,\n /<openclaw:heartbeat>[\\s\\S]*?<\\/openclaw:heartbeat>/g,\n];\n\nconst MAX_MESSAGE_CHARS = 4000;\n\nexport function isNoiseMessage(content: string): boolean {\n const trimmed = content.trim();\n if (trimmed.length === 0) return true;\n if (trimmed.length < 4) return true;\n return NOISE_PATTERNS.some((p) => p.test(trimmed));\n}\n\nexport function isGenericAssistantMessage(content: string): boolean {\n const trimmed = content.trim();\n // Only flag SHORT generic responses; long responses likely have substance\n if (trimmed.length > 200) return false;\n return GENERIC_ASSISTANT_PATTERNS.some((p) => p.test(trimmed));\n}\n\nexport function stripNoiseFromContent(content: string): string {\n let result = content;\n for (const pattern of NOISE_FRAGMENTS) {\n result = result.replace(pattern, \"\");\n }\n return result.trim();\n}\n\nexport function filterMessagesForExtraction(messages: Message[]): Message[] {\n const seen = new Set<string>();\n const filtered: Message[] = [];\n\n for (const msg of messages) {\n let content = stripNoiseFromContent(msg.content);\n\n if (isNoiseMessage(content)) continue;\n if (msg.role === \"assistant\" && isGenericAssistantMessage(content)) continue;\n\n // Truncate\n if (content.length > MAX_MESSAGE_CHARS) {\n content = `${content.slice(0, MAX_MESSAGE_CHARS)}…[truncated]`;\n }\n\n // Dedupe by exact content\n const key = `${msg.role}:${content}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n filtered.push({ role: msg.role, content });\n }\n\n return filtered;\n}\n","/**\n * Lifecycle hooks for openclaw-mind.\n *\n * Uses OpenClaw's `api.on(event, handler)` registration pattern.\n * - \"before_prompt_build\" — fires before a prompt is sent to the model.\n * Return { prependContext: string } to inject memories.\n * - \"agent_end\" — fires after an agent turn completes.\n */\n\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { MindClient } from \"../mind-client.js\";\nimport type { MindPluginConfig } from \"../config.js\";\nimport { isNonInteractiveTrigger, isSubagentSession } from \"../lib/session.js\";\nimport { filterMessagesForExtraction } from \"../lib/filter.js\";\n\n// Local stubs for hook event/context shapes. The OpenClaw plugin-sdk does\n// not re-export these from its public index, but the runtime delivers objects\n// matching these shapes (verified against\n// node_modules/openclaw/dist/plugin-sdk/src/plugins/types.d.ts at install time).\ninterface PluginHookBeforePromptBuildEvent {\n prompt: string;\n messages: unknown[];\n}\n\ninterface PluginHookBeforePromptBuildResult {\n systemPrompt?: string;\n prependContext?: string;\n}\n\ninterface PluginHookAgentEndEvent {\n messages: unknown[];\n success: boolean;\n error?: string;\n durationMs?: number;\n}\n\ninterface PluginHookAgentContext {\n trigger?: string;\n sessionKey?: string;\n}\n\ninterface ChatMessageLike {\n role?: string;\n content?: string;\n}\n\nexport function registerLifecycleHooks(\n api: OpenClawPluginApi,\n client: MindClient,\n config: MindPluginConfig,\n): void {\n if (config.autoRecall) {\n api.on(\n \"before_prompt_build\",\n async (\n event: PluginHookBeforePromptBuildEvent,\n ctx: PluginHookAgentContext,\n ): Promise<PluginHookBeforePromptBuildResult | void> => {\n try {\n if (isNonInteractiveTrigger(ctx?.trigger, ctx?.sessionKey)) return;\n if (isSubagentSession(ctx?.sessionKey)) return;\n\n const recallQuery = pickRecallQuery(event);\n if (!recallQuery || recallQuery.length < 5) return;\n\n const result = await client.query({\n query: recallQuery,\n mode: config.queryMode,\n top_k: config.topK,\n });\n\n if (!result.answer) return;\n\n const memoryContext = formatRecallContext(result);\n api.logger.debug?.(\n `mind auto-recall: injected ${result.sources?.length ?? 0} sources`,\n );\n\n // Canonical way to inject context — return prependContext\n return { prependContext: memoryContext };\n } catch (err) {\n api.logger.warn(`mind auto-recall failed: ${(err as Error).message}`);\n return;\n }\n },\n );\n }\n\n if (config.autoCapture) {\n api.on(\n \"agent_end\",\n async (\n event: PluginHookAgentEndEvent,\n ctx: PluginHookAgentContext,\n ): Promise<void> => {\n try {\n if (isNonInteractiveTrigger(ctx?.trigger, ctx?.sessionKey)) return;\n if (isSubagentSession(ctx?.sessionKey)) return;\n if (!event.success) return; // skip captures from failed turns\n\n const messages = (event.messages ?? []) as ChatMessageLike[];\n const normalized = messages\n .filter((m): m is { role: string; content: string } =>\n typeof m.role === \"string\" && typeof m.content === \"string\",\n )\n .map((m) => ({ role: m.role, content: m.content }));\n\n const filtered = filterMessagesForExtraction(normalized);\n if (filtered.length === 0) return;\n\n const conversationText = filtered\n .map((m) => `${m.role.toUpperCase()}: ${m.content}`)\n .join(\"\\n\\n\")\n .slice(0, 8000);\n\n await client.createEntry({\n content: conversationText,\n type: \"entry\",\n tags: [\"openclaw\", \"auto-capture\"],\n source: \"openclaw-mind\",\n });\n\n api.logger.debug?.(\"mind auto-capture: stored turn\");\n } catch (err) {\n api.logger.warn(`mind auto-capture failed: ${(err as Error).message}`);\n }\n },\n );\n }\n}\n\nfunction pickRecallQuery(event: PluginHookBeforePromptBuildEvent): string | undefined {\n if (event.prompt) return event.prompt;\n const messages = (event.messages ?? []) as ChatMessageLike[];\n const lastUser = [...messages].reverse().find((m) => m.role === \"user\");\n return typeof lastUser?.content === \"string\" ? lastUser.content : undefined;\n}\n\nfunction formatRecallContext(result: {\n answer: string;\n sources?: Array<{ title?: string }>;\n}): string {\n const sourceList = (result.sources ?? [])\n .slice(0, 5)\n .map((s, i) => `${i + 1}. ${s.title ?? \"(untitled)\"}`)\n .join(\"\\n\");\n\n return [\n \"## Persistent Memory (MIND knowledge graph)\",\n \"\",\n \"Context retrieved from the user's MIND knowledge graph based on the current request. Use it to inform your response.\",\n \"\",\n result.answer,\n sourceList ? `\\n**Sources:**\\n${sourceList}` : \"\",\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":["path","Type","Type","Type","Type","Type","Type","Type","Type","Type","Type","fs","path","os"]}
@@ -0,0 +1,178 @@
1
+ {
2
+ "id": "openclaw-mind",
3
+ "name": "MIND",
4
+ "description": "MIND personal knowledge graph for OpenClaw — true KG, 50+ AI models, MINDsense emotional intelligence, life management, CRM. Auto-recall injects relevant memories into context. Auto-capture extracts entities + relationships + emotional weights from each turn.",
5
+ "version": "0.1.0",
6
+ "kind": "memory",
7
+ "skills": ["skills"],
8
+ "contracts": {
9
+ "tools": [
10
+ "mind_search",
11
+ "mind_add",
12
+ "mind_get",
13
+ "mind_list",
14
+ "mind_update",
15
+ "mind_delete",
16
+ "mind_query_graph",
17
+ "mind_recall_emotional",
18
+ "mind_context",
19
+ "mind_life",
20
+ "mind_crm_log"
21
+ ]
22
+ },
23
+ "providerAuthEnvVars": {
24
+ "mind": ["MIND_API_KEY"]
25
+ },
26
+ "providerAuthChoices": [
27
+ {
28
+ "provider": "mind",
29
+ "method": "api-key",
30
+ "choiceId": "mind-api-key",
31
+ "choiceLabel": "MIND API key",
32
+ "choiceHint": "Get your key at https://www.m-i-n-d.ai → Settings → Developer → Create API Key. Starts with mind_",
33
+ "groupId": "mind",
34
+ "groupLabel": "MIND",
35
+ "optionKey": "apiKey",
36
+ "cliFlag": "--mind-api-key",
37
+ "cliOption": "--mind-api-key <key>",
38
+ "cliDescription": "MIND Developer API key (mind_...)"
39
+ }
40
+ ],
41
+ "uiHints": {
42
+ "apiKey": {
43
+ "label": "MIND API Key",
44
+ "sensitive": true,
45
+ "placeholder": "mind_...",
46
+ "help": "Get your key at https://www.m-i-n-d.ai → Settings → Developer. Use a SecretRef ({\"source\":\"env\",\"provider\":\"default\",\"id\":\"MIND_API_KEY\"}) or ${MIND_API_KEY} instead of storing the key directly."
47
+ },
48
+ "baseUrl": {
49
+ "label": "MIND Base URL",
50
+ "placeholder": "https://www.m-i-n-d.ai",
51
+ "help": "Override only if self-hosting MIND. Default points to the MIND cloud."
52
+ },
53
+ "userId": {
54
+ "label": "Default User ID",
55
+ "placeholder": "default",
56
+ "help": "User ID for scoping memories. Usually leave blank — your API key is already user-scoped."
57
+ },
58
+ "autoCapture": {
59
+ "label": "Auto-Capture",
60
+ "help": "Automatically extract facts, entities, and emotional weights from each agent turn into the MIND knowledge graph."
61
+ },
62
+ "autoRecall": {
63
+ "label": "Auto-Recall",
64
+ "help": "Automatically inject relevant memories from the MIND knowledge graph before each agent turn."
65
+ },
66
+ "topK": {
67
+ "label": "Top K Recall",
68
+ "placeholder": "10",
69
+ "help": "Maximum number of memories to inject per turn. Default: 10"
70
+ },
71
+ "searchThreshold": {
72
+ "label": "Search Threshold",
73
+ "placeholder": "0.5",
74
+ "help": "Minimum similarity score for hybrid search results (0-1). Default: 0.5"
75
+ },
76
+ "queryMode": {
77
+ "label": "Query Mode",
78
+ "help": "MIND knowledge graph query mode. Options: hybrid (default, recommended), mix, global, local, naive."
79
+ },
80
+ "enableMindsense": {
81
+ "label": "MINDsense Emotional Encoding",
82
+ "help": "Use MINDsense to assign valence/arousal weights to captured memories. Higher emotional content gets deeper KG encoding."
83
+ },
84
+ "enableLifeIntegration": {
85
+ "label": "Life Management Integration",
86
+ "help": "Allow the agent to create MIND Life items (tasks, goals, calendar events) from conversations."
87
+ },
88
+ "enableCrmLogging": {
89
+ "label": "CRM Activity Logging",
90
+ "help": "Allow the agent to log contacts and interaction history to MIND CRM."
91
+ },
92
+ "skills": {
93
+ "label": "Agentic Memory Skills",
94
+ "advanced": true,
95
+ "help": "Enable skills-based memory protocols. Triage gates incoming facts, dream consolidates the KG periodically, emotional-encoding scores valence/arousal, graph-recall traverses entity relationships."
96
+ }
97
+ },
98
+ "configSchema": {
99
+ "type": "object",
100
+ "additionalProperties": false,
101
+ "properties": {
102
+ "apiKey": {
103
+ "type": "string"
104
+ },
105
+ "baseUrl": {
106
+ "type": "string"
107
+ },
108
+ "userId": {
109
+ "type": "string"
110
+ },
111
+ "autoCapture": {
112
+ "type": "boolean"
113
+ },
114
+ "autoRecall": {
115
+ "type": "boolean"
116
+ },
117
+ "topK": {
118
+ "type": "number"
119
+ },
120
+ "searchThreshold": {
121
+ "type": "number"
122
+ },
123
+ "queryMode": {
124
+ "type": "string",
125
+ "enum": ["hybrid", "mix", "global", "local", "naive"]
126
+ },
127
+ "enableMindsense": {
128
+ "type": "boolean"
129
+ },
130
+ "enableLifeIntegration": {
131
+ "type": "boolean"
132
+ },
133
+ "enableCrmLogging": {
134
+ "type": "boolean"
135
+ },
136
+ "skills": {
137
+ "type": "object",
138
+ "properties": {
139
+ "triage": {
140
+ "type": "object",
141
+ "properties": {
142
+ "enabled": { "type": "boolean" },
143
+ "importanceThreshold": { "type": "number" },
144
+ "credentialPatterns": { "type": "array", "items": { "type": "string" } }
145
+ }
146
+ },
147
+ "recall": {
148
+ "type": "object",
149
+ "properties": {
150
+ "enabled": { "type": "boolean" },
151
+ "strategy": { "type": "string", "enum": ["always", "smart", "manual"] },
152
+ "tokenBudget": { "type": "number" },
153
+ "maxMemories": { "type": "number" }
154
+ }
155
+ },
156
+ "dream": {
157
+ "type": "object",
158
+ "properties": {
159
+ "enabled": { "type": "boolean" },
160
+ "auto": { "type": "boolean" },
161
+ "minHours": { "type": "number" },
162
+ "minSessions": { "type": "number" }
163
+ }
164
+ },
165
+ "emotionalEncoding": {
166
+ "type": "object",
167
+ "properties": {
168
+ "enabled": { "type": "boolean" },
169
+ "minValence": { "type": "number" },
170
+ "minArousal": { "type": "number" }
171
+ }
172
+ }
173
+ }
174
+ }
175
+ },
176
+ "required": []
177
+ }
178
+ }
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@astramindapp/openclaw-mind",
3
+ "version": "0.1.0",
4
+ "description": "MIND personal knowledge graph for OpenClaw — true KG, 50+ models, MINDsense emotional intelligence, life management, CRM. The most complete memory plugin for AI agents.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "openclaw.plugin.json",
18
+ "skills",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "dev": "tsup --watch",
25
+ "test": "vitest run",
26
+ "lint": "tsc --noEmit"
27
+ },
28
+ "keywords": [
29
+ "openclaw",
30
+ "openclaw-plugin",
31
+ "mind",
32
+ "mindapp",
33
+ "memory",
34
+ "knowledge-graph",
35
+ "personal-ai",
36
+ "long-term-memory",
37
+ "rag",
38
+ "ai-memory",
39
+ "emotional-intelligence",
40
+ "mindsense",
41
+ "crm",
42
+ "life-management"
43
+ ],
44
+ "author": "Astrai AI <hello@theastraway.com>",
45
+ "homepage": "https://www.m-i-n-d.ai/openclaw",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/theastraway/openclaw-mind.git"
49
+ },
50
+ "bugs": {
51
+ "url": "https://github.com/theastraway/openclaw-mind/issues"
52
+ },
53
+ "openclaw": {
54
+ "extensions": [
55
+ "./dist/index.js"
56
+ ],
57
+ "compat": {
58
+ "pluginApi": ">=2026.3.28",
59
+ "minGatewayVersion": ">=2026.3.28"
60
+ },
61
+ "build": {
62
+ "openclawVersion": "2026.4.1",
63
+ "pluginSdkVersion": "2026.4.1"
64
+ }
65
+ },
66
+ "dependencies": {
67
+ "@sinclair/typebox": "0.34.47"
68
+ },
69
+ "peerDependencies": {
70
+ "openclaw": ">=2026.3.28"
71
+ },
72
+ "devDependencies": {
73
+ "@types/node": "^22.0.0",
74
+ "openclaw": "^2026.4.9",
75
+ "tsup": "^8.3.0",
76
+ "typescript": "^5.7.0",
77
+ "vitest": "^3.0.0"
78
+ },
79
+ "engines": {
80
+ "node": ">=22"
81
+ }
82
+ }