ai

package module
v0.0.0-...-6a25a8b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 10 Imported by: 0

README

SOP AI Kit

The sop/ai package is the SOP AI Kit. It extends SOP with AI-oriented storage, retrieval, scripting, and model-integration components.

It supports:

  • Domain-Specific AI Copilots: Adapt the Scripting engine to any vertical (Finance, Healthcare, Media).
  • Embedded Applications: Combine the database + scripting engine for edge and local deployments.
  • Personal AI Copilots: Privacy-first, web-based assistants.
  • Enterprise AI Systems: ACID-compliant RAG and autonomous agents.

It provides components for building local AI applications on top of SOP's B-Tree storage engine.

Core Components

The core user-facing and agent-driven storage engine. It is the recommended approach for new applications. It provides human-readable ontologies, structured data for the UI and Copilot, visual analysis tools within the Data Manager, and user-manageable overrides.

  • Visual & Manageable: Data Manager provides full UI integration to see how information is categorized. Users can manually inspect, manage, and override how the AI linked concepts, creating user-enrichable AI memories.
  • Knowledge Bases: Groups information logically rather than physically. Implements the OpenKnowledgeBase pattern.
  • LLM Categorization: Unlike legacy systems that use mathematics, this system uses LLMs to read data and determine its Category (e.g., "Billing", "HR").
  • Deterministic Pre-Filtering: Caching and filtering by human-readable categories allows UI Copilots to skip 99% of the search space instantly before any math is done.
  • No Optimization Phase: The memory system shapes items into semantic categories during normal operation, so it does not require a blocking Optimize() phase like the legacy K-Means vector path.
  • Granular Items: The memory system inherently understands relationship mappings and structured JSON arrays for document retrieval.
  • Portable Knowledge Bases: Because this memory structure is user-manageable, Knowledge Bases can be reviewed in the UI, exported, and reused across environments.
2. K-Means Vector Database (ai/vector) (Supported)

A persistent, ACID-compliant vector store optimized for mathematical throughput. While the new memory architecture is recommended, the K-Means VectorDB remains supported for high-volume pipelines, backward compatibility, and cross-language FFI bindings.

  • Import Path to Spaces: Legacy vector content can be imported into the newer Memory Spaces model. This allows older vector datasets to remain usable while the maintained product surface shifts toward Dynamic Vector Store and KnowledgeBase Studio workflows.
  • Mathematical Centroids: Zero-LLM ingestion. Vectors are grouped into clusters (Centroids) by cosine distance. This avoids API calls during ingestion.
  • Blocking Optimizations (Weakness): Because centroids are purely mathematical, data drifts as vectors are added. It strictly requires periodic calls to the Optimize() function to recalculate the centers and shift data, during which writing may be blocked.
  • Storage: Uses SOP B-Trees to store vectors and metadata. Parallel queries point directly at mathematical clusters.
  • Usage: Suitable for high-volume ingestion pipelines and language-wrapper scenarios where mathematical clustering is preferred over category-oriented memory.
  • Modes: Supports Standalone (In-Memory Cache) for local use and Clustered (Redis Cache) for distributed deployments.
  • Search: Supports cosine similarity search with metadata filtering.
  • Partitioning: Designed to scale through natural partitioning.
  • Optimization: Built-in Optimize() method to rebalance clusters (Centroids) and ensure optimal search performance as data grows.
    • Scalability: The optimization process is batched (commits every 200 items), allowing it to scale to millions of records without hitting transaction timeouts.
    • Operational Constraint: To ensure data consistency and simplicity, the Vector Store enters a Read-Only mode during optimization. Any attempts to Upsert or Delete will return an error until Optimize completes.
    • Crash Recovery: If the process crashes during optimization, simply restart it. The next call to Optimize will automatically detect and clean up any stale artifacts before starting fresh.
    • Rolling Version Safety: When migrating items to a new optimization version, the system promotes the "Next" state to the "Current" state before overwriting it. This ensures that if the optimization process crashes mid-flight, the data remains accessible via the valid "Current" version, preventing data loss or corruption during the transition.
  • Deletion & Cleanup: Implements a Tombstone mechanism for efficient deletions.
    • Soft Delete: Delete() marks items as deleted in both the Index and Content stores, ensuring they are immediately hidden from search results.
    • Garbage Collection: The Optimize() process acts as a Garbage Collector. It detects these tombstones and performs a physical delete on the underlying data, reclaiming storage space during the maintenance cycle.
  • Deduplication: Optional deduplication check during ingestion. Can be disabled (SetDeduplication(false)) for maximum write performance when data is known to be unique.
  • Rich Key Structure: The Vector Store uses a specialized ContentKey struct as the B-Tree key.
    • Metadata Carrier: Stores CentroidID, Distance, Version, and Deleted status directly in the key.
    • Efficiency: Allows the system to perform structural operations (like filtering deleted items or finding vectors in a specific cluster) by scanning only the keys, without fetching the potentially large vector payload.
  • Usage Modes:
    • BuildOnceQueryMany: Optimized for static datasets. Ingest data -> Call Optimize() -> Serve queries. Discards temporary build artifacts for efficiency.
    • Dynamic: For systems with continuous updates. Maintains auxiliary structures to handle frequent inserts/deletes.
    • DynamicWithVectorCountTracking: Specialized mode for external centroid management (e.g., Agents). It tracks vector counts per centroid to help you decide when to trigger Optimize().
2. Versatile Scripting Engine (ai/agent)

The core of the Computing Platform. It allows you to define complex, multi-step workflows using Natural Language Programming (Scripts/Scripts).

  • Adaptable: Can be tailored to any domain (Finance, Media, etc.) by registering custom Tools.
  • Swarm Computing: Async execution of steps for high-performance parallel processing.
  • Agent Framework: Define agents with Personality, Memory, and Tool access.
  • Interoperable: Scripts are stored as JSON and can be managed/visualized via the SOP Data Manager.

See ai/agent/README.md for full documentation on Scripts, Swarm Computing, and the Tool Registry.

3. Memory Architecture (SOP Unique Design)

The SOP Agent is equipped with a dual-memory system that leverages the Database Engine itself:

  • Short-Term Memory (Session Context): Uses RunnerSession / ConversationThread to track Topics and Goals. Unlike standard chat history (flat list), this structured approach allows the Agent to maintain distinct threads of thought and switch contexts with clearer state boundaries.
  • Long-Term Memory (System Knowledge): Uses a persistent, transactional B-Tree (llm_knowledge). The Agent records reusable knowledge through ACID-backed storage rather than relying only on transient prompt context.
  • Persona Isolation: Knowledge Bases can carry distinct system prompts, embedders, and tool restrictions. Runtime memory is scoped to the active Knowledge Base so domain-specific personas do not bleed into unrelated asks.
  • System vs. Domain Roles: The runtime can keep a system-level supervisor for routing and policy while delegating domain reasoning to the active Knowledge Base persona.
4. Generators & Embedders (ai/generator, ai/embed)

Interfaces for connecting to AI models:

  • Generators: Connect to LLMs like OpenAI, Gemini, or local Ollama instances.
  • Embedders: Convert text to vectors. Includes a "Simple" keyword-based embedder (for testing) and an "Agent Embedder" (for semantic understanding).
Provider-Owned ReAct Loops

The generator layer supports both shared and provider-owned ReAct loops.

  • Providers that preserve native tool and conversation state can own the inner loop directly.
  • Providers without a native loop continue to use the shared engine path.
  • Carryover, repair continuity, and orchestration policy are documented in AI Copilot & Agent Architecture and Store Orchestration Modes.
4. Model Store (ai/database/model_store.go)

A unified interface for persisting AI models, from small "Skills" (Perceptrons) to large "Brains" (Neural Nets).

  • Backend: Uses transactional B-Tree storage (BTreeModelStore) for reliability and consistency.
  • Categorization: Models are stored with a composite key {Category, Name}, allowing for organized grouping of model artifacts.
  • Transactional: The B-Tree backend allows model updates to be part of the same ACID transaction as vector data changes.

A transactional, embedded text search engine.

  • ACID Compliant: Index documents within the same transaction as your data.
  • BM25 Scoring: Uses industry-standard ranking for relevance.
  • Architecture: Stores Inverted Indices in SOP B-Trees.
  • Usage: Ideal for "Search this wiki" or "Filter by text" features alongside Vector Search.
6. Script System (ai/SCRIPTS.md)

A Hybrid Execution engine that runs inside the Agent.

  • Explicit Execution: No magic, no guessing. The engine executes scripts line-by-line, exactly as defined.
  • Hybrid Workflows: Seamlessly mixes Deterministic Code (loop, fetch tables) with Non-Deterministic AI (ask "Analyze this data").
  • Optimization: Deterministic steps run in the local execution engine; AI steps are invoked only when explicit reasoning is required.
  • Read the full documentation.
7. AI Copilot (Interactive Mode)

A conversational interface for interacting with your data, building scripts, and managing AI Spaces.

Space Management and Search in AI Copilot

The AI Copilot is the interactive surface for the full Space lifecycle:

  1. Create / Mint a Space: Launch a new Knowledge Base, define its purpose, and seed its categories.
  2. Manage Categories and Items: Edit categories, add content, refine summaries, and organize the KB structure in the UI.
  3. Vectorize When Ready: Trigger full-space, category, or item vectorization once the curated content is ready.
  4. Search the Space: Ask the Copilot to search the active Space using semantic retrieval, text search, or combined retrieval paths.

This is the same user flow that developers can later reproduce in code with the ai package.

  • Natural Language Queries: "Select all users where role is admin".
  • CRUD Operations: Add, update, and delete records using plain English.
  • AI Spaces Management: Effortlessly generate, import, and manage "Spaces". A Space (or Knowledge Base) is a new AI memory subsystem combining VectorDB, Text Search, and a specialized schema (Thoughts: Category/Items).
  • Script Drafting: Teach the assistant workflows by defining them step-by-step.
  • Read the User Guide.
8. Knowledge Vectorization (Setup Wizard)

The AI Copilot does not hardcode context rules. Instead, it relies on an embedded Setup Wizard and an internal Vectorizer (compiler). When the system initializes, the Setup Wizard compiles documents like this README.md and the user/tool guides (AI_COPILOT_USAGE.md), converting guidelines, relational schema strategies, and tool lists directly into Active Memory (Vectors). This allows the AI to learn how your tables are linked, what tools it is allowed to use (select, join, script), and which CEL expressions map to your domain, directly from your documentation rather than rigid code blocks.

KnowledgeBase Studio and the Space import/export surfaces are also the forward path for moving legacy vector content into the maintained Memory Spaces model.

AI Tools

Standards & Compatibility

The SOP AI Kit is designed to play nicely with the broader AI ecosystem while adhering to strict software engineering standards.

Supported Interfaces
  • Generators (LLMs):
    • Google (Gemini): Native support for Gemini Pro. (Default & Tested)
    • OpenAI (ChatGPT): Native support for GPT-3.5/4.
    • Ollama: Native support for local models (Llama 3, Mistral, Gemma).
    • Custom: Implement the ai.Generator interface to connect any other provider.
  • Embedders:
    • Google Gemini embeddings: Supports gemini-embedding-2 through the Generative Language batchEmbedContents API. The runtime normalizes the model name to the models/... form and sends taskType=RETRIEVAL_DOCUMENT with outputDimensionality=768.
    • Ollama: Use local models for embeddings.
    • Local (kelindar / GGUF): Supports local GGUF embedders through the Kelindar integration, including nomic-embed-text-v1.5-q8_0 and bge-small-en-v1.5-q8_0.
    • Agent-as-Embedder: Use another SOP Agent to "embed" (translate) text, enabling recursive agent architectures.
  • Vector Store:
    • LangChain: The Python wrapper (sop4py) includes convenience methods for LangChain integration.
    • Generic: The Go API uses generics (VectorStore[T]), allowing you to store strongly-typed structs or dynamic map[string]any payloads.
Current embedder implementations

The current runtime has three documented embedder paths for the main local and hosted setups:

  • Gemini gemini-embedding-2: Hosted 768-dimensional embeddings via Google's batch endpoint. SOP sends retrieval-oriented payloads and explicitly requests outputDimensionality=768.
  • Kelindar / Nomic (nomic-embed-text-v1.5-q8_0): Local GGUF embedder with asymmetric prefixes for storage and query paths plus Matryoshka-style routing slices.
  • Kelindar / BGE Small (bge-small-en-v1.5-q8_0): Local GGUF embedder for lighter-weight 384-dimensional embeddings, especially useful for short labels, titles, and compact retrieval passages.
Local kelindar / Nomic GGUF notes

The default local embedding engine (nomic-embed-text) supports a native context window of 8,192 tokens (approximately 6,000 English words).

  • Automatic Handling: If a text block inside your batch exceeds this size, the library will automatically truncate the text down to the maximum allowed limit before generating the vector.
  • Safety: Your application will not crash, throw out-of-memory (OOM) exceptions, or panic when large documents are submitted.
  • Best Practice: For large documents, chunk or split strings before passing them to the embedder to avoid losing context during truncation.

For Kelindar models, SOP uses profile-driven behavior from embedder metadata:

  • Nomic Matryoshka routing: Category and routing vectors are sliced to the routing dimension and normalized after slicing when the profile marks the model as Matryoshka-capable.
  • BGE-small: The BGE small profile keeps 384-dimensional vectors and does not apply the Matryoshka routing normalization path.
  • Mode-specific prefixes: Local routing, document-storage, and query vectors can use different prefixes so storage and retrieval follow the model contract rather than a single generic embedding call.
Normalized vector distance path

For normalized vectors, SOP uses a faster distance path in the memory/vector math layer.

  • One-time normalization: Routing/category vectors from local Matryoshka models are normalized when they are sliced or indexed.
  • Fast distance: Distance(a, b, true) dispatches to a dot-product-based Euclidean form for normalized vectors.
  • Formula: For unit vectors, Euclidean distance is computed from the dot product as $\sqrt{2(1 - a \cdot b)}$.
  • Effect: This avoids recomputing norms inside the hot search loop while preserving the same ranking behavior expected from Euclidean distance on normalized vectors.
Deployment Standards
  • ACID Compliance: Full Two-Phase Commit (2PC) support for distributed transactions.
  • Storage: Uses standard filesystem paths (no proprietary binary blobs hidden in OS folders).
  • Caching: Supports standard Redis protocol for clustered caching. Note: Redis is NOT used for data storage, just for coordination & to offer built-in caching.
  • Replication & High Availability:
    • General Purpose: Supports full replication (Erasure Coding, Active/Passive) in all modes.
    • AI Package:
      • Standalone Mode: Supports replication if configured, though typically used for single-folder local storage.
      • Clustered Mode: Supports full replication. Configurable via VectorDBOptions (Python) or Database struct (Go). Replication is optional in both modes.

Unified Architecture

The SOP AI package is built as a high-level abstraction layer on top of the General Purpose SOP engine. This design ensures that both use cases share the same robust foundation while offering appropriate interfaces for their respective domains.

  • Shared Engine: Both packages use the same infs B-Tree storage engine, ensuring identical performance, reliability, and ACID compliance.
  • Separation of Concerns:
    • General Purpose (sop): Exposes low-level B-Tree primitives and explicit transaction management for building custom data structures (Key-Value stores, Registries).
    • AI Package (sop/ai): Abstracts B-Trees into domain-specific "Vector Stores" and "Model Stores" with implicit transaction handling for ease of use.
  • The Bridge: You can mix both worlds in a single atomic transaction. By creating a General Purpose transaction and "binding" an AI Store to it, you can update a User Profile (Key-Value) and their Embedding (Vector) simultaneously. See the Tutorial for an example.

API Cookbook

For detailed code examples and usage patterns, please see the AI Cookbook.

Model Store Tutorial

For a deep dive into persisting AI models, configurations, and weights, see the Model Store Tutorial.

Usage as a Library

You can use the ai package directly in your Go applications to build custom solutions.

Space Management in the App Runtime

The runtime-side flow mirrors the UI workflow:

  1. Open the authored Space with ai/database / ai/memory.
  2. Manage categories and items through the KnowledgeBase abstraction.
  3. Vectorize the Space or selected categories/items when you are ready to enable semantic retrieval.
  4. Search using the unified Search(...) API for keyword, semantic, and mixed retrieval flows.

This gives your application the same Space-aware reasoning path that the AI Copilot uses, while keeping the authoring experience in SOP Data Manager.

Authoring Spaces in SOP Data Manager, then consuming them in code

A common pattern is to use the SOP Data Manager as the authoring studio for your Knowledge Bases (Spaces), then consume the curated data from your application with the ai library:

  1. Create or curate a Space in the SOP Data Manager / Knowledge Base Studio UI.
  2. Use the ai/database package to open that Space in your Go code with OpenKnowledgeBase(...).
  3. Query it with the rich KnowledgeBase API, using Search(...) as the single entry point for retrieval in RAG or agent workflows.

This keeps the human-facing management and authoring experience in the UI, while your application uses the SOP AI runtime to manage, digest, and search the authored Spaces in-process.

Example: Building a Simple RAG App
package main

import (
    "context"
    "fmt"
    "github.com/sharedcode/sop/ai"
    "github.com/sharedcode/sop/database"
    "github.com/sharedcode/sop/ai/embed"
)

func main() {
    // 1. Initialize the Vector Database
    db := database.NewDatabase(sop.DatabaseOptions{
        Type:          sop.Standalone,
        StoresFolders: []string{"./my_knowledge_base"},
    })
    
    // 2. Start a Transaction
    ctx := context.Background()
    trans, _ := db.BeginTransaction(ctx, sop.ForWriting)
    defer trans.Rollback(ctx) // Safety rollback

    // 3. Open an index for a specific domain (e.g., "documents")
    idx, _ := db.OpenVectorStore(ctx, "documents", trans, vector.Config{})

    // 4. Initialize an Embedder
    // (In production, use a real embedding model. Here we use the simple keyword hasher)
    emb := embed.NewSimple("simple-embedder", 64, nil)

    // 5. Add Data (Upsert)
    item := ai.Item[map[string]any]{
        ID: "doc-1",
        Vector: nil, // Will be filled below
        Payload: map[string]any{
            "text": "SOP is a high-performance Go library for storage.",
            "category": "tech",
        },
    }
    // Generate vector
    vecs, _ := emb.EmbedTexts(ctx, []string{item.Payload["text"].(string)})
    item.Vector = vecs[0]

    // Save to DB
    idx.UpsertBatch(ctx, []ai.Item[map[string]any]{item})
    
    // Commit the transaction
    trans.Commit(ctx)

    // 6. Search (Retrieve) - New Read Transaction
    trans, _ = db.BeginTransaction(ctx, sop.ForReading)
    idx, _ = db.OpenVectorStore(ctx, "documents", trans, vector.Config{})
    
    query := "storage library"
    queryVecs, _ := emb.EmbedTexts(ctx, []string{query})
    
    hits, _ := idx.Query(ctx, queryVecs[0], 5, nil)
    
    for _, hit := range hits {
        fmt.Printf("Found: %s (Score: %.2f)\n", hit.Payload["text"], hit.Score)
    }
    trans.Commit(ctx)
}

The Doctor Demo: A Real RAG Pipeline powered by Gemini

This demo showcases a complete, real-world RAG (Retrieval-Augmented Generation) pipeline. It demonstrates how to chain agents and vector databases together using the SOP AI framework.

Specifically, it implements a genuine RAG flow:

  • Embedding (Text-to-Vector): Uses Google's Gemini API (gemini-embedding-001) to convert patient symptoms into vector embeddings.
  • Retrieval: Uses SOP's high-performance hybrid search (Vector + BM25) to locate the closest clinical mappings and disease data in your local stores.
  • Context-Aware Ranking (Active Memory): Intercepts the Reciprocal Rank Fusion (RRF) algorithm to mathematically boost documents (e.g., up to 1.5x) mathematically if they match the user's ongoing conversation/topic thread. This seamlessly solves the "forgetful RAG" problem for follow-up questions.
  • Generation (LLM): Uses Google's Gemini API (gemini-2.5-flash or similar) as the "Doctor" to synthesize the retrieved medical context and provide an educated diagnosis.

Architecture

The system consists of two agents working in a pipeline:

  1. Nurse Agent (nurse_local):

    • Role: The "Translator".
    • Task: Takes colloquial patient symptoms (e.g., "tummy hurt", "hot") and translates them into standardized clinical terms (e.g., "abdominal pain", "fever").
    • Mechanism: Uses a local vector database to find the closest matching clinical terms.
  2. Doctor Agent (doctor_pipeline):

    • Role: The "Diagnostician".
    • Task: Takes the clinical terms from the Nurse and searches its medical knowledge base to suggest possible conditions.
    • Mechanism: Uses a separate local vector database populated with disease-symptom mappings.

ETL Workflow (Data Ingestion)

Before the agents can run, we must build their knowledge bases. We use a dedicated ETL (Extract, Transform, Load) tool called sop-etl.

The entire process is defined in etl_workflow.json and consists of three steps:

  1. Prepare: Downloads a raw healthcare dataset (CSV) and converts it into JSON format (doctor_data.json).
  2. Build Nurse DB: Ingests the data into the Nurse's vector store (data/nurse_local), indexing symptoms for semantic retrieval.
  3. Build Doctor DB: Ingests the data into the Doctor's vector store (data/doctor_core), indexing diseases and their associated symptoms.

Quick Start

We provide a script to build the tools, run the ETL pipeline, and verify the agents.

  1. Run the Rebuild & Demo Script:

    ./run_demo_gemini.sh
    

    This script will:

    • Initialize necessary dependencies.
    • Clean up old local databases.
    • Run the ETL pipeline via go run main.go in the demo folder to ingest data (handling Gemini API 429 rate limits seamlessly with backoffs).
    • Automatically launch the interactive doctor repl.
  2. Run the Agent Manually (Interactive REPL): Once the data is built (using the ETL pipelines or scripts like ./run_demo_gemini.sh), you can chat with the Doctor agent in a fully interactive terminal session powered by Gemini 2.5 Flash and robust Hybrid Search (Vector + BM25):

    go run ai/cmd/demo_doctor/main.go
    

    Example Interaction:

    Patient> I have a bad cough and a runny nose
    ...Doctor is thinking (and searching)...
    
    🩺 Doctor Answer:
    Based on your symptoms...
    

Configuration Files

  • etl_workflow.json: Defines the ETL pipeline steps and parameters (e.g., batch sizes, input/output paths).
  • data/doctor_pipeline.json: Configuration for the main Doctor agent. It specifies that it should use the nurse_local agent as its "embedder" (translator).
  • data/nurse_local.json: Configuration for the Nurse agent.

Heuristic vs LLM Embedders

The system supports two types of "Nurse" agents for embedding/translation:

  1. Heuristic Agent (nurse_local):

    • How it works: Uses a local dictionary and vector search with manually curated synonyms.
    • Performance: Extremely fast and deterministic.
    • Use Case: Default for this demo. Tuned for high performance in specific areas (e.g., lung-related diseases).
    • Pros: No external dependencies (no Ollama required), predictable.
    • Cons: Requires manual tuning for new slang/terms.
  2. LLM Agent (nurse_translator):

    • How it works: Uses a local LLM (via Ollama) to semantically understand and translate user input.
    • Performance: Slower (depends on GPU/CPU), but more flexible.
    • Use Case: General-purpose understanding without manual synonym mapping.
    • Pros: Understands context and nuance better out-of-the-box.
    • Cons: Requires running Ollama, higher latency.

To switch between them, you would update the embedder configuration in the agent's JSON file.

Knowledge Compiler & Setup Wizard Integration

To dramatically speed up the instantiation of the SOP intelligent agent environment, we provide a Knowledge Compiler (ai/cmd/knowledge_compiler/main.go). This tool pre-compiles baseline architectural knowledge into a static blob (ai/sop_base_knowledge.json).

Instead of waiting for the LLM or embedding endpoints during the first run, the SOP Setup Wizard UI automatically catches this JSON payload. When configuring endpoints (e.g., via the frontend fetch('/api/config/save') integration), a unified loading screen directly injects the compiled vectors into your target databases synchronously alongside your Demo Data or Medical Expert configurations.

Engine Constraints & Query Rules (Behavioral Vectors)
  • Query Filtering: When filtering with select, use MongoDB-style operators ($eq, $ne, $gt, $gte, $lt, $lte) for comparisons. Example: {"age": {"$gt": 18}}.
  • Sorting: Sorting/Ordering is ONLY supported by the store's Key or a prefix of the Key. You CANNOT sort by arbitrary fields (e.g. salary, date) unless they are the Key.
  • Secondary Indexes: Check if a secondary index store exists (e.g., users_by_age). If so, use it to fulfill sort/filter requests by joining it with the main store (e.g. scan users_by_age and join users). If no index exists, explain that SOP only supports sorting by Key.
Scripting & Join Execution Strategies
  • Join Strategy:
    • Use inner (default) when the query implies "intersection" or strict matching (e.g., "Find orders for user X").
    • Use left (Left Outer Join) when the query implies "optional" relationships.
    • Use right or full only if explicitly requested or logically required.
  • Return Values:
    • The return command in a script must refer to an EXPLICIT variable name defined in a previous step (e.g., 'result_var': "my_data" -> 'return {"value": "my_data"}').
    • Do NOT assume a variable named final_result exists unless you created it.
  • Contextual Projection:
    • When joining entities, ALWAYS project identifying fields (e.g., Name, Email) from the parent/source entity alongside the child data in the final result.
    • Do NOT return orphaned child records without their parent's context if the user filtered by the parent.
    • Always use the Store Name as prefix (e.g., users.age) or the explicit Alias defined in the join step.
Critical Aliasing Rules
  • STRICTLY FORBIDDEN: Do NOT use right.*, left.*, l.*, or r.* in projection fields. Using right.* will fail.
  • You MUST list specific fields (e.g., orders.key, users.name) or use the exact store name wildcard (e.g., orders.*) if applicable.
Intent Detection (Conversation vs. Action)
  • Distinguish between a request to PERFORM an action (e.g., "Add a user", "Find records") and a request to GENERATE data or EXPLAIN concepts (e.g., "Give me a new UUID", "How does this work?").
  • If a user asks for a "new UUID" or "random ID" in isolation, simply generate it and reply with the text. Do NOT add it to any store unless explicitly instructed to "save" or "add" it.
  • Engage in conversation freely to clarify intent before taking destructive or additive actions.
UI Handlers (Client-Side Actions)
  • To switch the active database context in the UI, do NOT use a tool. Instead, strictly output the following text in your final response: [[SWITCH_DATABASE: <db_name>]]. The frontend will detect this and perform the switch.
Active Memory & Self-Correction
  • Your pipeline is powered by an automated Context-Aware "Active Memory" backend.
  • When correcting mistakes or learning rules (e.g., "We use 'TotalAmount', not 'Cost'"), simply ACKNOWLEDGE the prompt. The vector retrieval backend natively handles the propagation of definitions without you needing to explicitly 'save' them. Proceed immediately with corrected logic.

Documentation

Index

Constants

View Source
const (
	// Default Models
	DefaultModelOpenAI = "gpt-5.4"
	DefaultModelGemini = "gemini-3.5-flash"
	DefaultModelOllama = "llama3"

	// Default Application Configurations
	DefaultScriptCategory = "general"

	// Agent Types
	AgentTypeCopilot = "copilot"
	AgentIDOmni      = "omni"
	IntentOmni       = "OMNI"

	// Knowledge Base Constants
	DefaultKBName = "SOP"
)
View Source
const (
	// MemoryHydrationToolCallLimit caps the number of recent tool calls retained
	// in a provisional in-loop hydration update.
	MemoryHydrationToolCallLimit = 6
	// MemoryHydrationOutcomeFactLimit caps the number of recent grounded facts
	// retained in a provisional in-loop hydration update.
	MemoryHydrationOutcomeFactLimit = 6
	// MemoryHydrationTextCharLimit caps provisional final text and carryover
	// assistant summaries retained for in-loop hydration.
	MemoryHydrationTextCharLimit = 600
	// MemoryHydrationFactCharLimit caps each grounded fact retained for
	// provisional in-loop hydration.
	MemoryHydrationFactCharLimit = 240
)
View Source
const (
	ReasoningEventAssistantMessage = "assistant_message"
	ReasoningEventToolCall         = "tool_call"
	ReasoningEventToolResult       = "tool_result"
	ReasoningEventToolError        = "tool_error"
)

Variables

This section is empty.

Functions

func BuildAssistantMessageEvent

func BuildAssistantMessageEvent(phase, text string) map[string]any

func BuildStreamingAssistantMessageEvent

func BuildStreamingAssistantMessageEvent(phase, text, itemID, source, streamState string) map[string]any

func BuildStreamingToolCallEvent

func BuildStreamingToolCallEvent(tool, itemID, callID, streamState string) map[string]any

func BuildToolCallEvent

func BuildToolCallEvent(tool string, args map[string]any, iteration int) map[string]any

func BuildToolErrorEvent

func BuildToolErrorEvent(tool string, args map[string]any, err error, iteration int) map[string]any

func BuildToolResultEvent

func BuildToolResultEvent(tool string, args map[string]any, result string, hint *ToolProgressHint, iteration int) map[string]any

func CanonicalKBName

func CanonicalKBName(name string) string

CanonicalKBName returns the canonical system KB identifier for known names.

func IsNewTopicFromContext

func IsNewTopicFromContext(ctx context.Context) bool

IsNewTopicFromContext returns the is-new-topic flag stamped into the context by applyAskOptions. Returns false if the flag was not set (treat as topic continuation).

func SummarizeOutcomeFacts

func SummarizeOutcomeFacts(toolResults []ReActToolResult) []string

func SummarizeSuccessfulToolResult

func SummarizeSuccessfulToolResult(result ReActToolResult) []string

func ValidateScript

func ValidateScript(steps []ScriptStep) error

ValidateScript checks a slice of ScriptSteps for logical errors, such as using a variable before it has been declared.

Types

type AI

type AI struct {
	// Provider is the default AI provider to use.
	Provider string `json:"Provider,omitempty"`
	// CacheTTL is the cache duration for AI providers that support it (e.g., "5m", "1h").
	CacheTTL string `json:"CacheTTL,omitempty"`
	// EndPoint is the AI provider's endpoint.
	EndPoint string `json:"Endpoint,omitempty"`
}

type Agent

type Agent[T any] interface {
	// Lifecycle methods
	Open(ctx context.Context) error
	Close(ctx context.Context) error

	Search(ctx context.Context, query string, limit int) ([]Hit[T], error)
	Ask(ctx context.Context, query string, cfg *ConfigMap) (string, error)
}

Agent defines the interface for an AI agent service.

type AgentControl

type AgentControl interface {
	// Stop aborts the current operation.
	Stop() error
	// Pause suspends the agent's activities (if supported).
	Pause() error
	// Resume resumes the agent's activities.
	Resume() error
}

AgentControl defines methods to manage the agent's lifecycle. This allows the Application to control the Agent (e.g. Stop/Pause).

type ArtifactReference

type ArtifactReference struct {
	Name            string              `json:"name"`
	Type            ArtifactType        `json:"type"`
	DatabaseName    string              `json:"db_name"`
	DatabaseOptions sop.DatabaseOptions `json:"db_opts,omitempty"`
}

ArtifactReference is a unified structure to pass globally referenced DB Artifacts (KB, Space, etc.) containing the exact location, avoiding the need to cycle through available databases.

type ArtifactType

type ArtifactType string

ArtifactType represents the type of a database artifact.

const (
	ArtifactTypeSpace ArtifactType = "Space"
	ArtifactTypeStore ArtifactType = "Store"
)

type CarryoverCapability

type CarryoverCapability struct {
	Provider        string
	Model           string
	SupportsCompact bool
	SupportsLive    bool
}

type CarryoverCapabilityProvider

type CarryoverCapabilityProvider interface {
	CarryoverCapability() CarryoverCapability
}

CarryoverCapabilityProvider is an optional generator extension that lets a provider declare whether it can participate in compact or live carryover across adjacent asks.

type CarryoverMode

type CarryoverMode string
const (
	CarryoverModeOff     CarryoverMode = "off"
	CarryoverModeCompact CarryoverMode = "compact"
	CarryoverModeLive    CarryoverMode = "live"
)

type CarryoverPolicy

type CarryoverPolicy struct {
	DefaultMode             CarryoverMode
	LiveCarryoverMaxAsks    int
	LiveCarryoverIdleTTL    time.Duration
	LiveCarryoverSoftTokens int
	LiveCarryoverHardTokens int
	MaxRawToolCarryTokens   int
}

func DefaultCarryoverPolicy

func DefaultCarryoverPolicy() CarryoverPolicy

type CarryoverResetReason

type CarryoverResetReason string
const (
	CarryoverResetNone                CarryoverResetReason = ""
	CarryoverResetDisabled            CarryoverResetReason = "disabled"
	CarryoverResetUnsupportedProvider CarryoverResetReason = "unsupported_provider"
	CarryoverResetMissingState        CarryoverResetReason = "missing_state"
	CarryoverResetLiveContinuation    CarryoverResetReason = "live_continuation"
	CarryoverResetTopicSwitch         CarryoverResetReason = "topic_switch"
	CarryoverResetProviderChanged     CarryoverResetReason = "provider_changed"
	CarryoverResetModelChanged        CarryoverResetReason = "model_changed"
	CarryoverResetKBChanged           CarryoverResetReason = "kb_changed"
	CarryoverResetExpired             CarryoverResetReason = "expired"
	CarryoverResetBudgetExceeded      CarryoverResetReason = "budget_exceeded"
	CarryoverResetCompactContinuation CarryoverResetReason = "compact_continuation"
)

type CarryoverState

type CarryoverState struct {
	Mode                   CarryoverMode
	Provider               string
	Model                  string
	ConversationHandle     string
	ConversationID         string
	TopicFingerprint       string
	KBFingerprint          string
	StartedAtUnixMilli     int64
	LastUsedAtUnixMilli    int64
	AskCount               int
	EstimatedCarryTokens   int
	EstimatedRawToolTokens int
	LastOutcomeFacts       []string
	LastRecipeIDs          []string
	LastToolNames          []string
	LastUserQuery          string
	LastAssistantSummary   string
	LastResetReason        CarryoverResetReason
}

type Centroid

type Centroid struct {
	Vector      []float32
	VectorCount int
}

Centroid represents a cluster center and its metadata.

type ClarificationState

type ClarificationState struct {
	TargetQuery        string
	AssistantQuestion  string
	OriginalUserQuery  string
	UserClarification  string
	EffectiveResumeAsk string
	Status             string
}

ClarificationState tracks a pending assistant clarification before the target ask resumes.

type Classifier

type Classifier interface {
	// Name returns the name of the classifier.
	Name() string
	// Classify analyzes the content and returns a list of labels.
	Classify(ctx context.Context, sample ContentSample) ([]Label, error)
}

Classifier defines the interface for content classification models.

type ConfigMap

type ConfigMap struct {
	// contains filtered or unexported fields
}

ConfigMap holds configuration parameters for Agent.Ask calls. This is the "goo" type used at the Agent interface boundary for pipeline flexibility. Individual agent implementations should define their own typed structs and convert from ConfigMap.

func NewConfigMap

func NewConfigMap() *ConfigMap

NewConfigMap creates a new empty ConfigMap.

func (*ConfigMap) Get

func (c *ConfigMap) Get(key string) (any, bool)

func (*ConfigMap) Set

func (c *ConfigMap) Set(key string, value any)

func (*ConfigMap) ToMap

func (c *ConfigMap) ToMap() map[string]any

ToMap returns the underlying map for marshaling/conversion.

type ContentKey

type ContentKey struct {
	ItemID         string  `json:"id"`
	CentroidID     int     `json:"cid"`
	Distance       float32 `json:"dist"`
	Version        int64   `json:"ver"`
	Deleted        bool    `json:"del"`
	NextCentroidID int     `json:"ncid"`
	NextDistance   float32 `json:"ndist"`
	NextVersion    int64   `json:"nver"`
}

ContentKey is the key for the Content B-Tree. It includes metadata to allow updates without modifying the Value segment (Payload).

SOP's key structure handling allows apps to ride data in it that acts as persistent space as well without affecting the overall key/value pair behaviour and BTree ness. This means critical metadata (like Version, CentroidID, Deleted flag) is available during key traversal (e.g. Range scans) without needing to fetch the potentially large Value payload.

type ContentSample

type ContentSample struct {
	Text string
	Meta map[string]any
}

ContentSample represents the content being evaluated for safety.

type ContextKey

type ContextKey string

ContextKey is a type for context keys used in the AI package.

const (
	// CtxKeyProvider is the context key for overriding the AI provider.
	CtxKeyProvider ContextKey = "ai_provider"
	// CtxKeyAPIKey is the context key for passing a transient API key
	CtxKeyAPIKey ContextKey = "ai_api_key"
	// CtxKeyBaseURL is the context key for passing a transient Base URL
	CtxKeyBaseURL ContextKey = "ai_base_url"
	// CtxKeyAppBaseURL is the context key for passing the public app origin used to build absolute viewer links.
	CtxKeyAppBaseURL ContextKey = "ai_app_base_url"
	// CtxKeyExecutor is the context key for passing the ToolExecutor.
	CtxKeyExecutor ContextKey = "ai_executor"
	// CtxKeyDeobfuscator is the context key for passing the Deobfuscator.
	CtxKeyDeobfuscator ContextKey = "ai_deobfuscator"
	// CtxKeyHistory is the context key for passing conversation history.
	CtxKeyHistory ContextKey = "ai_history"
	// CtxKeyWriter is the context key for passing an io.Writer for streaming output.
	CtxKeyWriter ContextKey = "ai_writer"
	// CtxKeyDatabase is the context key for passing the target database for script execution.
	CtxKeyDatabase ContextKey = "ai_database"
	// CtxKeyResultStreamer is the context key for passing the ResultStreamer.
	CtxKeyResultStreamer ContextKey = "ai_result_streamer"
	// CtxKeyScriptRecorder is the context key for passing the ScriptRecorder.
	CtxKeyScriptRecorder ContextKey = "ai_script_recorder"
	// CtxKeyAutoFlush is the context key for enabling/disabling auto-flush (boolean).
	CtxKeyAutoFlush ContextKey = "ai_auto_flush"
	// CtxKeyDefaultFormat is the context key for carrying the requested default output format.
	CtxKeyDefaultFormat ContextKey = "ai_default_format"
	// CtxKeyProgressSink is the context key for passing a structured progress emitter callback.
	CtxKeyProgressSink ContextKey = "ai_progress_sink"
	// CtxKeyEventStreamer is the context key for passing a structured event emitter callback.
	CtxKeyEventStreamer ContextKey = "ai_event_streamer"
	// CtxKeyNativeToolHints marks native Ask-loop tool execution that can consume structured progress hints.
	CtxKeyNativeToolHints ContextKey = "ai_native_tool_hints"
	// CtxKeyIsNewTopic carries the is-new-topic signal from the orchestrating Service down to pipeline agents.
	// When true it indicates the current request starts a fresh conversation thread rather than continuing one.
	CtxKeyIsNewTopic ContextKey = "ai_is_new_topic"
)

type Database

type Database interface {
	BeginTransaction(ctx context.Context, mode sop.TransactionMode, maxTime ...time.Duration) (sop.Transaction, error)
	Config() sop.DatabaseOptions
}

Database interface abstracts the ability to begin a transaction and provide config. It is implemented by ai/database.Database.

type DefaultReActTurnStrategy

type DefaultReActTurnStrategy struct{}

DefaultReActTurnStrategy preserves the generic synthetic-prompt behavior. It exists as an explicit implementation so providers can extend or replace it.

func (DefaultReActTurnStrategy) PrepareTurn

type Deobfuscator

type Deobfuscator interface {
	Deobfuscate(text string) string
}

Deobfuscator defines the interface for de-obfuscating text.

type Domain

type Domain[T any] interface {
	ID() string
	Name() string
	Embedder() Embeddings
	// Index returns the vector index used for retrieval.
	// It requires a transaction to be passed in.
	Index(ctx context.Context, tx sop.Transaction) (VectorStore[T], error)
	// Memory returns the new Cognitive Knowledge Base for retrieval and episodic reasoning.
	// Returns any to prevent circular dependencies with the memory package.
	Memory(ctx context.Context, tx sop.Transaction) (any, error)
	// TextIndex returns the text search index used for retrieval.
	TextIndex(ctx context.Context, tx sop.Transaction) (TextIndex, error)
	// BeginTransaction starts a new transaction for the domain's underlying storage.
	BeginTransaction(ctx context.Context, mode sop.TransactionMode) (sop.Transaction, error)
	Policies() PolicyEngine
	Classifier() Classifier
	Prompt(ctx context.Context, kind string) (string, error)
	DataPath() string
}

Domain represents a vertical or specific AI application domain.

type EmbeddingModeSupport

type EmbeddingModeSupport interface {
	EmbedCategoryTexts(ctx context.Context, texts []string) ([][]float32, error)
	EmbedDocumentTexts(ctx context.Context, texts []string) ([][]float32, error)
	EmbedQueryTexts(ctx context.Context, texts []string) ([][]float32, error)
}

EmbeddingModeSupport adds explicit storage/search/category embedding modes. Implementers may use different prefixes or truncation depths for each path.

type Embeddings

type Embeddings interface {
	// Name returns the name of the embedding model.
	Name() string
	// Dim returns the dimension of the embeddings.
	Dim() int
	// EmbedTexts generates embeddings for a batch of texts.
	EmbedTexts(ctx context.Context, texts []string) ([][]float32, error)
}

Embeddings defines the interface for generating vector embeddings from text.

type GenOptions

type GenOptions struct {
	SystemPrompt     string
	MaxTokens        int
	Temperature      float32
	ForceTemperature bool
	TopP             float32
	Stop             []string
	Tools            []ToolDefinition // NEW: Pass the schemas via Native API
	// ToolCallContinuations carries provider-neutral tool-call/result turns that a
	// generator can translate into its provider-specific continuation format.
	ToolCallContinuations []ToolCallContinuation
	// ThinkingLevel controls internal reasoning intensity for Gemini 3.1 Pro (low/medium/high).
	// Use "low" for strict structured outputs, "high" for creative tasks.
	ThinkingLevel string
	// ResponseSchema enforces strict output structure by physically constraining token generation.
	// Pass a JSON schema to prevent hallucinated fields/keys.
	ResponseSchema map[string]any
}

GenOptions configures the generation process.

type GenOutput

type GenOutput struct {
	Text       string
	TokensUsed int
	Raw        any
	ToolCalls  []ToolCall // NEW: Struct for natively parsed tool requests
}

GenOutput represents the result of a generation.

type Generator

type Generator interface {
	// Name returns the name of the generator.
	Name() string
	// Generate produces text based on the provided prompt and options.
	Generate(ctx context.Context, prompt string, opts GenOptions) (GenOutput, error)
	// PrewarmCache sends a request to the provider to cache the provided
	// options (e.g., SystemPrompt, Tools) without generating a response.
	// This is used for just-in-time, predictive caching.
	PrewarmCache(ctx context.Context, opts GenOptions) error
	// EstimateCost calculates the estimated cost of the generation.
	EstimateCost(inTokens, outTokens int) float64
}

Generator defines the interface for an LLM or text generation model.

type Hit

type Hit[T any] struct {
	ID      string
	DocID   []string
	Score   float32
	Payload T
}

Hit represents a search result.

type Item

type Item[T any] struct {
	ID         string
	Vector     []float32
	Payload    T
	CentroidID int // Optional: Explicitly assign to a centroid (0 = auto)
}

Item represents a vector item returned to the user.

type KnowledgeBasePayload

type KnowledgeBasePayload struct {
	DatasetName string              `json:"dataset_name,omitempty"`
	Documents   []KnowledgeDocument `json:"documents"`
}

KnowledgeBasePayload represents the standard JSON payload structure used for streaming or batch-loading documents into a Vector DB.

type KnowledgeDocument

type KnowledgeDocument struct {
	ID          string                 `json:"id,omitempty"`
	Text        string                 `json:"text,omitempty"`
	PageContent string                 `json:"page_content,omitempty"`
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
}

KnowledgeDocument represents a single unit of embeddable contextual information commonly used to standardize preloading Vector DBs and RAG pipelines.

type Label

type Label struct {
	Name   string
	Score  float32
	Source string
}

Label represents a classification result (e.g., "profanity", "hate_speech").

type LearnedRecipe

type LearnedRecipe struct {
	ID         string
	Kind       string
	Scope      string
	Domain     string
	Topic      string
	Trigger    string
	Protocol   []string
	Invariants []string
	Confidence float64
	Source     string
}

LearnedRecipe captures a reusable protocol distilled from successful reasoning behavior. It is intentionally separate from grounded facts.

func SummarizeOutcomeRecipes

func SummarizeOutcomeRecipes(toolResults []ReActToolResult) []LearnedRecipe

type MemoryHydrationSink

type MemoryHydrationSink func(update MemoryHydrationUpdate)

type MemoryHydrationUpdate

type MemoryHydrationUpdate struct {
	FinalText      string
	ToolCalls      []ToolCall
	OutcomeFacts   []string
	OutcomeRecipes []LearnedRecipe
	CarryoverState *CarryoverState
}

func BuildMemoryHydrationUpdate

func BuildMemoryHydrationUpdate(resp ReasoningResponse) MemoryHydrationUpdate

BuildMemoryHydrationUpdate adapts a full provider-owned response into the narrower provisional hydration contract. Prefer BuildMemoryHydrationUpdateFromParts in provider loops when a full response is not otherwise needed.

func BuildMemoryHydrationUpdateFromParts

func BuildMemoryHydrationUpdateFromParts(update MemoryHydrationUpdate) MemoryHydrationUpdate

BuildMemoryHydrationUpdateFromParts normalizes provider-owned in-loop progress into the bounded, grounded shape expected by the provisional MRU sink. Provider-owned loops should prefer this narrower helper so they do not need to manufacture a full ReasoningResponse just to emit hydration.

type ModelStore

type ModelStore interface {
	// Save persists a model with the given name and category.
	// The model can be any serializable object (e.g., Perceptron, NeuralNet).
	Save(ctx context.Context, category string, name string, model any) error

	// Load retrieves a model by name and category and populates the provided object.
	// The target parameter must be a pointer to the model struct.
	Load(ctx context.Context, category string, name string, target any) error

	// List returns the names of all stored models in a given category.
	List(ctx context.Context, category string) ([]string, error)

	// Delete removes a model from the store.
	Delete(ctx context.Context, category string, name string) error
}

ModelStore defines the interface for persisting and retrieving AI models. It allows for the management of "Skills" (small models) and "Brains" (large models).

type PolicyDecision

type PolicyDecision struct {
	Action   string   // "allow", "block", "flag"
	Reasons  []string // Why the action was taken
	PolicyID string
}

PolicyDecision represents the outcome of a policy evaluation.

type PolicyEngine

type PolicyEngine interface {
	// Evaluate checks the content against the policy rules.
	Evaluate(ctx context.Context, stage string, sample ContentSample, labels []Label) (PolicyDecision, error)
}

PolicyEngine defines the interface for evaluating content against safety policies.

type ReActLoop

type ReActLoop interface {
	Run(ctx context.Context, req ReasoningRequest) (ReasoningResponse, error)
}

ReActLoop owns a full multi-turn ReAct loop lifecycle rather than just a single-turn prompt adaptation.

type ReActLoopPhase

type ReActLoopPhase string
const (
	ReActLoopPhaseActive            ReActLoopPhase = "active"
	ReActLoopPhaseRepair            ReActLoopPhase = "repair"
	ReActLoopPhaseClarification     ReActLoopPhase = "clarification"
	ReActLoopPhaseMalformedToolCall ReActLoopPhase = "malformed_tool_call"
)

type ReActLoopProvider

type ReActLoopProvider interface {
	ReActLoop() ReActLoop
}

ReActLoopProvider lets generators return a provider-owned ReAct loop that can take over retry, repair, continuation, and termination policy end-to-end.

type ReActLoopState

type ReActLoopState struct {
	Iteration                int
	AllowedIterations        int
	MaxIterations            int
	RemainingToolCalls       int
	RepairAttempts           int
	Phase                    ReActLoopPhase
	AllowedNextActions       []ReActNextAction
	PendingRepair            *ReActPendingRepair
	PendingMalformedToolCall bool
	ToolResults              []ReActToolResult
	ToolCallContinuations    []ToolCallContinuation
}

ReActLoopState captures the current loop-owned state so provider-owned loops can observe or eventually own the same transition surface.

type ReActNextAction

type ReActNextAction string
const (
	ReActNextActionCallTool         ReActNextAction = "call_tool"
	ReActNextActionRetrySameTool    ReActNextAction = "retry_same_tool"
	ReActNextActionAskClarification ReActNextAction = "ask_clarification"
	ReActNextActionAnswerUser       ReActNextAction = "answer_user"
)

type ReActPendingRepair

type ReActPendingRepair struct {
	ToolName       string
	Strategy       string
	ResearchTool   string
	ResearchReason string
}

ReActPendingRepair is a provider-neutral snapshot of a pending repair path.

type ReActPromptBypassStrategy

type ReActPromptBypassStrategy interface {
	ShouldBypassPrompt(turn ReActTurn) bool
}

ReActPromptBypassStrategy is an optional strategy hook that lets a provider skip generic synthetic prompt construction when carried tool-call state is sufficient to continue the interaction.

type ReActToolResult

type ReActToolResult struct {
	Name   string
	Args   map[string]any
	Result string
	Hint   *ToolProgressHint
}

ReActToolResult is the provider-neutral per-step state that the ReAct engine can expose to provider-specific loop adapters.

type ReActTurn

type ReActTurn struct {
	Iteration       int
	UserQuery       string
	Prompt          string
	RepairDirective string
	LoopState       ReActLoopState
	Options         GenOptions
	ToolResults     []ReActToolResult
	FinalTurn       bool
}

ReActTurn captures a single ReAct generation turn before it reaches a provider-specific generator. Providers can adapt the prompt/options while the engine retains ownership of retry policy and tool execution.

type ReActTurnStrategy

type ReActTurnStrategy interface {
	PrepareTurn(ctx context.Context, turn ReActTurn) ReActTurn
}

ReActTurnStrategy is the shared loop-facing contract for shaping a single ReAct generation turn before it reaches the provider transport.

type ReActTurnStrategyProvider

type ReActTurnStrategyProvider interface {
	ReActTurnStrategy() ReActTurnStrategy
}

ReActTurnStrategyProvider lets generators return a provider-specific ReAct loop implementation while the engine keeps ownership of retry and execution policy.

type ReasoningEngine

type ReasoningEngine interface {
	Run(ctx context.Context, req ReasoningRequest) (ReasoningResponse, error)
}

ReasoningEngine isolates the orchestration loop from the service configuration.

type ReasoningRequest

type ReasoningRequest struct {
	SystemPrompt   string
	ContextText    string
	HistoryText    string
	UserQuery      string
	Executor       ToolExecutor
	Generator      Generator
	CarryoverMode  CarryoverMode
	CarryoverState *CarryoverState
	HydrationSink  MemoryHydrationSink
	Streamer       func(eventType string, data any) // Optional NDJSON callback
	// Verbose enables structured progress/tool-result streaming during the reasoning loop.
	Verbose bool
	// ForceToolCall instructs provider-owned loops to set tool_choice=required so
	// the model must emit a tool call rather than a conversational text response.
	ForceToolCall bool
}

type ReasoningResponse

type ReasoningResponse struct {
	FinalText      string
	ToolCalls      []ToolCall // For audit/logging
	OutcomeFacts   []string   // Compact grounded facts safe to carry into outer MRU continuity
	OutcomeRecipes []LearnedRecipe
	// CarryoverState lets provider-owned loops return updated continuity metadata,
	// such as a reusable live conversation handle, without exposing transport
	// details to the service layer.
	CarryoverState *CarryoverState
}

type ResultStreamer

type ResultStreamer interface {
	// BeginArray starts a JSON array output.
	BeginArray()
	// SetMetadata sets metadata for the result (e.g. headers, record counts).
	// Should be called before the first WriteItem.
	SetMetadata(meta map[string]any)
	// WriteItem writes a single item to the output (e.g. an element of an array).
	WriteItem(item any)
	// EndArray ends the JSON array output.
	EndArray()
}

ResultStreamer defines the interface for streaming tool results.

type RetryRewriteState

type RetryRewriteState struct {
	OriginalQuery string
	ResolvedQuery string
	Status        string
}

RetryRewriteState tracks a retry-the-same-ask rewrite through Gate 0.

type Script

type Script struct {
	Description string   `json:"description"`
	Parameters  []string `json:"parameters"`         // Input parameters for the script
	Database    string   `json:"database,omitempty"` // Database to run the script against
	Portable    bool     `json:"portable,omitempty"` // If true, allows running on any database
	// TransactionMode specifies how transactions are handled for this script.
	// Values: "none" (default, manual), "single" (one tx for all steps), "per_step" (auto-commit each step)
	TransactionMode string       `json:"transaction_mode,omitempty"`
	Steps           []ScriptStep `json:"steps"`
}

Script represents a recorded sequence of user interactions or a programmed script.

type ScriptRecorder

type ScriptRecorder interface {
	RecordStep(ctx context.Context, step ScriptStep)
	// RefactorLastSteps refactors the last N steps into a new structure (script or block).
	// count: number of steps to refactor.
	// mode: "script" (extract to new named script) or "block" (group into block step).
	// name: name of the new script (if mode is "script").
	RefactorLastSteps(count int, mode string, name string) error
}

ScriptRecorder is an interface for recording script steps.

type ScriptStep

type ScriptStep struct {
	// Type of the step.
	// Valid values: "ask", "set", "if", "loop", "fetch", "say", "command", "call_script" (or "script"), "block"
	Type string `json:"type"`

	// Name acts as a label or identifier for the step.
	// It can be used for UI display or referenced in complex flows.
	Name string `json:"name,omitempty"`

	// --- Fields for "ask" (LLM Interaction) ---
	// Prompt is the question or command to send to the LLM. Supports templating.
	Prompt string `json:"prompt,omitempty"`
	// OutputVariable is where the LLM's response will be stored.
	// If empty, the response is just printed.
	OutputVariable string `json:"output_variable,omitempty"`
	// InputVariable is the variable to use as input for this step.
	InputVariable string `json:"input_variable,omitempty"`

	// --- Fields for "set" (Variable Assignment) ---
	// Variable is the name of the variable to set.
	Variable string `json:"variable,omitempty"`
	// Value is the value to assign. Supports templating.
	Value string `json:"value,omitempty"`

	// --- Fields for "if" (Flow Branching) ---
	// Condition is a Go template expression that must evaluate to "true".
	// Example: "{{ gt .count 5 }}"
	Condition string `json:"condition,omitempty"`
	// Then is the list of steps to execute if the condition is true.
	Then []ScriptStep `json:"then,omitempty"`
	// Else is the list of steps to execute if the condition is false.
	Else []ScriptStep `json:"else,omitempty"`

	// --- Fields for "loop" (Iteration) ---
	// List is the variable name or expression evaluating to a list/slice to iterate over.
	List string `json:"list,omitempty"`
	// Iterator is the variable name for the current item in the loop.
	Iterator string `json:"iterator,omitempty"`
	// Steps is the list of steps to execute for each item.
	// Also used for "block" type to hold the sequence of steps.
	Steps []ScriptStep `json:"steps,omitempty"`

	// --- Fields for "fetch" (Data Retrieval) ---
	// Database specifies the database name (optional). If empty, uses the current context database.
	Database string `json:"database,omitempty"`
	// Source specifies the data source type (e.g., "btree", "vector_store").
	Source string `json:"source,omitempty"`
	// Resource specifies the name of the resource (e.g., table name).
	Resource string `json:"resource,omitempty"`
	// Filter is an optional filter expression (not yet fully implemented).
	Filter string `json:"filter,omitempty"`

	// --- Fields for "say" (Output) ---
	// Message is the text to output to the user. Supports templating.
	Message string `json:"message,omitempty"`

	// --- Fields for "command" (Direct Tool Execution) ---
	// Command is the name of the tool/command to execute.
	Command string `json:"command,omitempty"`
	// Args are the arguments for the command.
	Args map[string]any `json:"args,omitempty"`

	// --- Fields for "call_script" (Nested Script Execution) ---
	// ScriptName is the name of the script to execute.
	ScriptName string `json:"script_name,omitempty"`
	// ScriptArgs are the arguments to pass to the script.
	ScriptArgs map[string]string `json:"script_args,omitempty"`

	// --- Async Execution ---
	// IsAsync specifies if the step should be executed asynchronously.
	// If true, the step runs in a goroutine and the script continues to the next step.
	// All async steps are gathered (waited for) at the end of the script execution.
	IsAsync bool `json:"is_async,omitempty"`

	// ContinueOnError specifies if the script should continue executing if this step fails.
	// If false (default), the script stops and returns the error.
	// For async steps, if this is false and the step fails, it cancels the execution of other steps.
	ContinueOnError bool `json:"continue_on_error,omitempty"`

	// --- Documentation ---
	// Description provides a human-readable explanation of what this step does.
	// It is used for documentation and self-explanation of the script.
	Description string `json:"description,omitempty"`
}

ScriptStep represents a single instruction in a script. It follows a stabilized schema for "Natural Language Programming".

type SessionPayload

type SessionPayload struct {
	// CurrentDB is the active database name for the session.
	CurrentDB string
	// CurrentUserQuery stores the raw user request for the current Ask interaction.
	// It is used sparingly for narrow tool fallbacks when the model omits a required arg.
	CurrentUserQuery string
	// UserID identifies the user for privacy and memory isolation.
	UserID string
	// ClientID tags the origin client device or application.
	ClientID string
	// SessionID tracks the specific transient connection/session.
	SessionID string
	// AvatarScope tags the session with the active KBContextID.
	// Used by Omni-Protocol to know which sandbox the conversation occurred within.
	AvatarScope string
	// AgentID represents whether Omni or a specific Avatar generated this payload/memory
	AgentID string
	// ActiveDomain is the knowledge domain selected by the user.
	ActiveDomain string
	// SelectedKBs are the explicit Knowledge Bases selected by the user from the dropdown.
	SelectedKBs []ArtifactReference
	// Transaction holds the active transaction for the session.
	// Deprecated: Migrate usage to TransactionPool.
	Transaction any
	// TransactionPool manages active transactions, their configurations, and pooling across the session.
	TransactionPool *TransactionPool
	// Transactions holds active transactions keyed by database name.
	// Deprecated: Migrate usage to TransactionPool.
	Transactions map[string]any
	// Variables holds session-scoped variables (e.g. cached store instances).
	Variables map[string]any
	// ExplicitTransaction marks when language bindings (Python, Rust, Java, .NET) are managing
	// their own transaction lifecycle via manage_transaction API.
	//
	// When ExplicitTransaction = true:
	//   - Transaction is managed EXTERNALLY by language binding code
	//   - SessionPayload.Close() will NOT auto-commit or auto-rollback
	//   - Language bindings must explicitly call commit/rollback via manage_transaction
	//   - This allows transactions to span multiple API calls (e.g., HTTP requests)
	//
	// When ExplicitTransaction = false (default):
	//   - Transaction is managed INTERNALLY by the agent session
	//   - SessionPayload.Close() will auto-commit the transaction
	//   - Transaction lifecycle is scoped to a single Ask/Execute call
	//
	// WARNING: ExplicitTransaction = true is prone to transaction leaks if language bindings
	// don't properly commit/rollback. Only use when you need multi-request transaction scope.
	ExplicitTransaction bool
	// RetryRewriteState tracks an explicit retry-the-same-ask rewrite.
	RetryRewriteState *RetryRewriteState
	// ClarificationState tracks an explicit pending clarification round before execution resumes.
	ClarificationState *ClarificationState
	// LastInteractionSteps tracks the number of steps added/executed in the last user interaction.
	LastInteractionSteps int
	// ConversationHistory stores the active memory/transcript for the session.
	ConversationHistory string
}

SessionPayload represents the context and state for an agent session. It carries domain-specific artifacts like database connections.

func GetSessionPayload

func GetSessionPayload(ctx context.Context) *SessionPayload

GetSessionPayload retrieves the session payload from the context.

func (*SessionPayload) Close

func (sp *SessionPayload) Close(ctx context.Context) error

Manages Payload's cleanup, e.g. Transaction Commit/Rollback.

func (*SessionPayload) GetDatabase

func (s *SessionPayload) GetDatabase() string

type TextIndex

type TextIndex interface {
	// Add indexes a document.
	Add(ctx context.Context, docID string, text string) error
	// Search performs a text search.
	Search(ctx context.Context, query string) ([]search.TextSearchResult, error)
}

TextIndex defines the interface for a text search index.

type ToolCall

type ToolCall struct {
	Name string
	Args map[string]any
	// NativeID carries the provider-native tool/function call identifier when one exists.
	// It is intentionally transport-agnostic so engines can round-trip tool continuity
	// across Gemini, OpenAI, Anthropic, or future providers without hard-coding one API shape.
	NativeID string
	// TransportMeta preserves provider-specific fields that may be needed to continue a
	// native tool-calling session without flattening everything into prompt text.
	TransportMeta map[string]any
}

ToolCall represents a native tool call requested by the LLM.

type ToolCallContinuation

type ToolCallContinuation struct {
	ToolCall ToolCall
	Response any
}

ToolCallContinuation preserves a completed tool-call turn so generators can continue a provider-native function-calling exchange without flattening the tool response back into plain prompt text.

type ToolDefinition

type ToolDefinition struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	// Schema is a JSON schema string describing the arguments.
	Schema string `json:"schema"`
}

ToolDefinition describes a tool available to the agent.

type ToolExecutor

type ToolExecutor interface {
	// Execute runs a named tool with the provided arguments.
	Execute(ctx context.Context, toolName string, args map[string]any) (string, error)
	// ListTools returns the list of available tools.
	ListTools(ctx context.Context) ([]ToolDefinition, error)
}

ToolExecutor defines the interface for the application to expose capabilities to the Agent. This allows the Agent to "act" on the application (e.g. query DB, send email).

type ToolProgressHint

type ToolProgressHint struct {
	Status             string   `json:"status,omitempty"`
	CompletionDelta    float64  `json:"completion_delta,omitempty"`
	Confidence         float64  `json:"confidence,omitempty"`
	Missing            []string `json:"missing,omitempty"`
	Tips               []string `json:"tips,omitempty"`
	Clues              []string `json:"clues,omitempty"`
	SuggestedNextTools []string `json:"suggested_next_tools,omitempty"`
}

ToolProgressHint is an optional progress envelope that a tool can return to guide the native Ask loop toward the next narrowing step without directly mutating scratchpad state.

type ToolResultEnvelope

type ToolResultEnvelope struct {
	ToolResult   json.RawMessage   `json:"tool_result,omitempty"`
	ProgressHint *ToolProgressHint `json:"progress_hint,omitempty"`
}

ToolResultEnvelope is an optional JSON result shape that tools can return. If present, `tool_result` remains the user-visible payload while `progress_hint` feeds the engine's internal progress and retry budgeting.

type TransactionPool

type TransactionPool struct {
	// contains filtered or unexported fields
}

TransactionPool caches and manages database transactions for the duration of a session or ReAct loop. This prevents the overhead of repeatedly calling BeginTransaction/Rollback on the same database.

func NewTransactionPool

func NewTransactionPool() *TransactionPool

NewTransactionPool initializes an empty TransactionPool.

func (*TransactionPool) CommitAll

func (p *TransactionPool) CommitAll(ctx context.Context) error

CommitAll iterations through all active pooled transactions and commits them. Note: In distributed DB contexts, a partial commit failure might leave things half-committed. You must evaluate if a distributed saga is needed for your use case.

func (*TransactionPool) GetOrBegin

func (p *TransactionPool) GetOrBegin(ctx context.Context, dbName string, db Database, mode sop.TransactionMode, exclusive bool) (sop.Transaction, error)

GetOrBegin tries to return an existing transaction for dbName. If one hasn't been opened yet, it creates one using the provided database and mode. If an existing transaction is found but it's Exclusive, or if the new request needs Exclusive access, it cannot be reused. Furthermore, if an existing shared transaction is ForReading and the new request needs ForWriting, it returns an error.

func (*TransactionPool) Has

func (p *TransactionPool) Has(dbName string) bool

Has checks if a transaction is currently opened for the specific dbName

func (*TransactionPool) Remove

func (p *TransactionPool) Remove(dbName string)

Remove cleanly drops a transaction reference from the pool without calling rollback or commit. This allows caller to manually commit a specific database's transaction if needed.

func (*TransactionPool) RollbackAll

func (p *TransactionPool) RollbackAll(ctx context.Context)

RollbackAll iterates through all active pooled transactions and rolls them back. Useful to defer at the start of a ReAct/Copilot loop function.

type TransactionPoolEntry

type TransactionPoolEntry struct {
	Transaction     sop.Transaction
	Mode            sop.TransactionMode
	DatabaseOptions sop.DatabaseOptions
	DatabaseName    string
	Exclusive       bool
}

TransactionPoolEntry tracks an active transaction, the mode it was opened with, and the configuration.

func (*TransactionPoolEntry) AddPhasedTransaction

func (e *TransactionPoolEntry) AddPhasedTransaction(otherTransaction ...sop.TwoPhaseCommitTransaction)

AddPhasedTransaction proxies to the wrapped transaction.

func (*TransactionPoolEntry) Begin

func (e *TransactionPoolEntry) Begin(ctx context.Context) error

Begin proxies to the wrapped transaction.

func (*TransactionPoolEntry) Close

func (e *TransactionPoolEntry) Close() error

Close proxies to the wrapped transaction.

func (*TransactionPoolEntry) Commit

func (e *TransactionPoolEntry) Commit(ctx context.Context) error

Commit proxies to the wrapped transaction.

func (*TransactionPoolEntry) CommitMaxDuration

func (e *TransactionPoolEntry) CommitMaxDuration() time.Duration

CommitMaxDuration proxies to the wrapped transaction.

func (*TransactionPoolEntry) GetID

func (e *TransactionPoolEntry) GetID() sop.UUID

GetID proxies to the wrapped transaction.

func (*TransactionPoolEntry) GetPhasedTransaction

func (e *TransactionPoolEntry) GetPhasedTransaction() sop.TwoPhaseCommitTransaction

GetPhasedTransaction proxies to the wrapped transaction.

func (*TransactionPoolEntry) GetStores

func (e *TransactionPoolEntry) GetStores(ctx context.Context) ([]string, error)

GetStores proxies to the wrapped transaction.

func (*TransactionPoolEntry) HasBegun

func (e *TransactionPoolEntry) HasBegun() bool

HasBegun proxies to the wrapped transaction.

func (*TransactionPoolEntry) OnCommit

func (e *TransactionPoolEntry) OnCommit(callback func(ctx context.Context) error)

OnCommit proxies to the wrapped transaction.

func (*TransactionPoolEntry) Rollback

func (e *TransactionPoolEntry) Rollback(ctx context.Context) error

Rollback proxies to the wrapped transaction.

type UsageMode

type UsageMode int

UsageMode defines how the vector database is intended to be used.

const (
	// BuildOnceQueryMany optimizes for a single ingestion phase followed by read-only queries.
	// Temporary structures (TempVectors, Lookup) are deleted after indexing to save space.
	BuildOnceQueryMany UsageMode = iota

	// DynamicWithVectorCountTracking optimizes for continuous updates (CRUD).
	// It maintains necessary metadata (like vector counts per centroid) to support
	// future rebalancing and structural adjustments.
	DynamicWithVectorCountTracking

	// Dynamic optimizes for continuous updates (CRUD). Does not maintain metadata like vector counts.
	// Useful for scenarios where the Agent explicitly manages the Centroids & Vector assignments.
	Dynamic
)

type VectorKey

type VectorKey struct {
	CentroidID         int
	DistanceToCentroid float32
	ItemID             string
	// IsDeleted marks this key as a Tombstone.
	// It ensures the Optimize process can find this entry and physically delete
	// the corresponding data from the Content store.
	IsDeleted bool
}

VectorKey is the key for the Vectors B-Tree.

type VectorStore

type VectorStore[T any] interface {
	// Upsert adds or updates a single item in the store.
	// It now accepts an Item[T] which includes the Vector, Payload, and optional CentroidID.
	Upsert(ctx context.Context, item Item[T]) error
	// UpsertBatch adds or updates multiple items in the store efficiently.
	UpsertBatch(ctx context.Context, items []Item[T]) error
	// Get retrieves an item by its ID.
	Get(ctx context.Context, id string) (*Item[T], error)
	// Delete removes an item by its ID.
	Delete(ctx context.Context, id string) error
	// Query searches for the nearest neighbors to the given vector.
	// filters is a function that returns true if the item should be included.
	Query(ctx context.Context, vec []float32, k int, filter func(T) bool) ([]Hit[T], error)
	// Count returns the total number of items in the store.
	Count(ctx context.Context) (int64, error)
	// AddCentroid adds a new centroid to the store dynamically.
	// This allows for runtime expansion of the concept space without full rebalancing.
	AddCentroid(ctx context.Context, vec []float32) (int, error)

	// SplitCentroid reorganizes an overloaded centroid by running localized 2-Means
	// clustering, creating two new centroids, and reassigning its vectors.
	SplitCentroid(ctx context.Context, centroidID int) error

	// Optimize reorganizes the index to improve query performance.
	// It re-calculates centroids based on the full dataset and re-distributes vectors.
	// This is recommended after a large batch ingestion (BuildOnceQueryMany mode) to "Seal" the index.
	Optimize(ctx context.Context) error

	// Consolidate reads accumulated vectors from short-term memory (TempVectors),
	// dynamically routes them into existing Centroids using AssignAndIndex logic,
	// and clears them from short-term memory.
	Consolidate(ctx context.Context) error

	// UpdateEmbedderInfo updates the configuration defining which embedder was used
	// to index the vectors, persisting it in the system configuration of the store.
	UpdateEmbedderInfo(ctx context.Context, provider string, model string, dimensions int) error

	// SetDeduplication enables or disables the internal deduplication check during Upsert.
	// Disabling this can speed up ingestion for pristine data but may lead to ghost vectors if duplicates exist.
	SetDeduplication(enabled bool)

	// Centroids returns the Centroids B-Tree for advanced manipulation.
	Centroids(ctx context.Context) (btree.BtreeInterface[int, Centroid], error)
	// Vectors returns the Vectors B-Tree for advanced manipulation.
	Vectors(ctx context.Context) (btree.BtreeInterface[VectorKey, []float32], error)
	// Content returns the Content B-Tree for advanced manipulation.
	Content(ctx context.Context) (btree.BtreeInterface[ContentKey, string], error)
	// Lookup returns the Sequence Lookup B-Tree for advanced manipulation (e.g. random sampling).
	Lookup(ctx context.Context) (btree.BtreeInterface[int, string], error)

	// Version returns the Vector store's version number, which is a unix elapsed time.
	Version(ctx context.Context) (int64, error)
}

VectorStore defines the interface for a vector database domain (like a table).

Directories

Path Synopsis
cmd
agent command
etl command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL