Skip to main content
Glama

localnest_memory_capture_event

Capture background work events and automatically promote meaningful ones into durable local memory for AI agents.

Instructions

Ingest a background work event and auto-promote meaningful events into durable memory.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
event_typeNotask
statusNocompleted
titleYes
summaryNo
contentNo
kindNoknowledge
importanceNo
confidenceNo
files_changedNo
has_testsNo
tagsNo
linksNo
scopeNo
source_refNo
response_formatNojson

Implementation Reference

  • The registration of the 'localnest_memory_capture_event' tool. It calls the `memory.captureEvent` method.
    registerJsonTool(
      ['localnest_memory_capture_event'],
      {
        title: 'Memory Capture Event',
        description: 'Ingest a background work event and auto-promote meaningful events into durable memory.',
        inputSchema: {
          event_type: MEMORY_EVENT_TYPE_SCHEMA,
          status: MEMORY_EVENT_STATUS_SCHEMA,
          title: z.string().min(1).max(400),
          summary: z.string().max(4000).default(''),
          content: z.string().max(20000).default(''),
          kind: MEMORY_KIND_SCHEMA.optional(),
          importance: z.number().int().min(0).max(100).optional(),
          confidence: z.number().min(0).max(1).optional(),
          files_changed: z.number().int().min(0).max(10000).default(0),
          has_tests: z.boolean().default(false),
          tags: z.array(z.string()).max(50).default([]),
          links: z.array(MEMORY_LINK_SCHEMA).max(50).default([]),
          scope: MEMORY_SCOPE_SCHEMA,
          source_ref: z.string().max(1000).default('')
        },
        annotations: {
          readOnlyHint: false,
          destructiveHint: false,
          idempotentHint: false,
          openWorldHint: false
        }
      },
      async (args) => memory.captureEvent(args)
    );
  • The main handler implementation for `captureEvent`. It processes the input, determines if an event should be promoted to memory, and performs the necessary database operations.
    export async function captureEvent(adapter, input, { storeEntry, updateEntry }) {
      const scope = normalizeScope(input.scope);
      const eventType = cleanString(input.event_type || input.eventType || 'task', 60) || 'task';
      const rawContent = cleanString(input.content, 20000);
      const summary = deriveSummary(input.summary, rawContent);
      const content = rawContent || summary;
      const title = deriveTitle({
        title: input.title,
        summary,
        content,
        eventType,
        scope
      });
      const tags = ensureArray(input.tags);
      const links = normalizeLinks(input.links);
      const sourceRef = cleanString(input.source_ref || input.sourceRef, 1000);
      const createdAt = nowIso();
      const signalScore = computeSignalScore({
        eventType,
        status: input.status,
        importance: input.importance,
        filesChanged: input.files_changed || input.filesChanged,
        hasTests: input.has_tests || input.hasTests,
        tags,
        title,
        content,
        summary
      });
      const promotionThreshold = getPromotionThreshold({
        eventType,
        status: input.status,
        title,
        summary,
        content
      });
    
      if (!title) throw new Error('title is required');
      if (!content && !summary) throw new Error('content or summary is required');
    
      const record = {
        eventType,
        title,
        summary,
        content: content || summary,
        scope,
        tags,
        links,
        sourceRef,
        signalScore,
        status: signalScore >= promotionThreshold ? 'processed' : 'ignored'
      };
    
      let promotedMemoryId = null;
      if (signalScore >= promotionThreshold) {
        const memoryKind = input.kind || (eventType === 'preference' ? 'preference' : 'knowledge');
        const mergeTarget = await findMergeCandidate(adapter, {
          kind: memoryKind,
          title,
          summary,
          content: content || summary,
          scope,
          tags
        });
    
        if (mergeTarget) {
          const merged = await updateEntry(mergeTarget.id, {
            summary: mergeText(mergeTarget.summary, summary),
            content: mergeText(mergeTarget.content, content || summary),
            tags: Array.from(new Set([...(mergeTarget.tags || []), ...tags])),
            links: Array.from(new Map(
              [...(mergeTarget.links || []), ...links].map((item) => [`${item.path}:${item.line || 0}`, item])
            ).values()),
            importance: Math.max(
              mergeTarget.importance || 0,
              input.importance || 0,
              Math.min(95, Math.round(signalScore * 20))
            ),
            confidence: Math.max(
              mergeTarget.confidence || 0,
              input.confidence || 0,
              Math.min(0.95, 0.45 + (signalScore * 0.1))
            ),
            change_note: `Auto-captured merge from ${eventType} event`
          });
          promotedMemoryId = merged.id;
          record.status = 'merged';
        } else {
          const result = await storeEntry({
            kind: memoryKind,
            title,
            summary,
            content: content || summary,
            status: input.memory_status || 'active',
            importance: input.importance === undefined ? Math.min(95, Math.round(signalScore * 20)) : input.importance,
            confidence: input.confidence === undefined ? Math.min(0.95, 0.45 + (signalScore * 0.1)) : input.confidence,
            tags,
            links,
            scope,
            source_type: 'capture-event',
            source_ref: sourceRef,
            change_note: `Auto-captured from ${eventType} event`
          });
          promotedMemoryId = result.memory?.id || null;
          record.status = result.duplicate ? 'duplicate' : 'promoted';
        }
      }
    
      const insert = await adapter.run(
        `INSERT INTO memory_events(
          event_type, title, summary, content, status, signal_score, promoted_memory_id,
          scope_root_path, scope_project_path, scope_branch_name, topic, feature,
          tags_json, links_json, source_ref, created_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          record.eventType,
          record.title,
          record.summary,
          record.content,
          record.status,
          signalScore,
          promotedMemoryId,
          scope.root_path,
          scope.project_path,
          scope.branch_name,
          scope.topic,
          scope.feature,
          stableJson(tags),
          stableJson(links),
          sourceRef,
          createdAt
        ]
      );
    
      return {
        event_id: insert.lastInsertRowid,
        event_type: eventType,
        signal_score: Number(signalScore.toFixed(2)),
        promotion_threshold: Number(promotionThreshold.toFixed(2)),
        status: record.status,
        promoted_memory_id: promotedMemoryId
      };
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wmt-mobile/localnest'

If you have feedback or need assistance with the MCP directory API, please join our Discord server