Download the PHP package ineersa/hatfield-ext-observational-memory without Composer

On this page you can find all versions of the php package ineersa/hatfield-ext-observational-memory. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package hatfield-ext-observational-memory

Observational Memory (OM) extension

Extension-owned observational memory storage, asynchronous Observer pipeline, threshold Reflector + Dropper generations, and CompactRun replacement summaries via instant durable-memory projection.

Architecture (OM-03 + OM-04 + OM-05)

Hatfield provides a generic async extension-agent job facility. OM uses the existing single FIFO extension_agent transport/worker for Observer/Reflector/Dropper model work. Compaction does not wait on that worker.

OM does not own a private Symfony Kernel, bin/console, Messenger bus, consumer supervisor, or priority/multi-receiver queue.

Live TUI status notices

While an Observer/Reflector/Dropper model stage is running, the async worker writes a single ephemeral om_current_activity row (per session/run). The TUI polls that row through the public TuiExtensionContextInterface::onTick bridge (self-throttled to ≥250ms) and sets status key om-background with Pi-style copy, e.g. Observational memory: reflector running (~2,500 tokens). The row is cleared in handler finally (job-id guarded); crash leftovers older than 5 minutes are hidden. Status writes never fail model work.

Freshness tradeoff (accepted)

Compaction renders whatever durable memory is already present. Observer/Reflector/Dropper work finishing later affects a later compaction. Canonical events.jsonl remains the source of truth for recall and later Observer catch-up on turn boundaries.

FIFO / failures (async observe + threshold only)

Async transport requirement

ExtensionAgentJobDispatcher is fail-closed for sync://.

The controller exports the session's broker socket in the DSN. The queue name is extension_agent, without a session suffix.

Mode HATFIELD_EXTENSION_AGENT_TRANSPORT_DSN
Process controller (production async) sqlite-queue://extension_agent?endpoint=<URL-encoded broker socket>
Unit tests in-memory://… or a mock bus with a sqlite-queue:// DSN
Default .env sync:// refused at dispatch

Activation

OM is not enabled by default. Tracked project .hatfield/settings.yaml omits the extension class from extensions.enabled and ships an inert nested observational_memory settings example. Activate by listing the class under extensions.enabled and configuring one shared exact model:

Install package dependencies into the project extension Composer root:

Ownership boundaries

Commands, search, and recall

Search implementation notes

Without semantic settings, memory_search uses escaped SQL LIKE substring matching with a small result limit. Under default SQLite settings (and OM does not enable case_sensitive_like), ASCII letter case is insensitive, so MapTool matches maptool. % and _ in the query are treated as literals via ESCAPE.

Date filters accept real calendar values only (YYYY-MM-DD or YYYY-MM-DD HH:MM). after must not be later than before. Date-only bounds cover the whole day. An HH:MM before bound includes the entire minute for reflection created_at values.

Benchmark evidence (read-only disposable copies; never modify the live OM database) is recorded under .hatfield/extensions/observational-memory/docs/om-search-like-benchmark.md, including the exact commands used on representative (~4.9k observations) and disposable 50k-row corpora. Leading-wildcard LIKE stayed in the low-millisecond to ~15 ms range for identifier queries such as 2510 and MapToolArguments, with SCAN om_observation plans. FTS5 was faster at 50k rows but needs schema/index maintenance and weaker exact-substring fidelity for punctuation-heavy identifiers. Exact mode keeps bounded LIKE search; hybrid mode has a separate derived FTS index.

Optional hybrid retrieval

Configure extensions.settings.observational_memory.semantic to enable hybrid retrieval. The example below is not enabled by default:

Omit semantic to keep literal-substring search without indexing work. The endpoint URLs and model IDs in the example are not defaults.

Key under semantic Meaning Default
embedding_api.base_url OpenAI-compatible embedding base URL Required
embedding_api.model_id Embedding model ID Required
embedding_api.query_prefix Query-only prefix, joined with one space Empty
embedding_api.chunk_bytes Maximum UTF-8-safe document chunk size in bytes 1200
embedding_api.overlap_bytes Chunk overlap in bytes, rounded to a UTF-8 boundary 192
embedding_api.max_lines Maximum lines per document chunk 80
embedding_api.batch_size Inputs per request; each indexing job processes at most four 4
reranker_api.base_url Base URL for the /rerank endpoint Required when configured
reranker_api.model_id Reranker model ID Required when configured
reranker_api.batch_size Maximum documents per rerank request 8
reranker_api.document_characters Maximum Unicode characters per reranked chunk 768
reranker_api.min_score Inclusive minimum finite raw reranker score for a chunk Unset, no score filter

Each configured API block requires base_url and model_id. Omit reranker_api to use fused keyword and vector ranking without reranking. A reranker without embeddings is a configuration error. The embedding prefix defaults to empty. It applies only to query embeddings, joined with one space. The reranker receives the raw query. The embedding example includes the colon required by this model. Batch sizes, line limits, and document character limits must be positive. chunk_bytes must be at least four; overlap_bytes must be nonnegative and smaller than the chunk. Requests run serially with a ten-second HTTP limit. An indexing job embeds at most four chunks, even if a larger provider batch size is configured. reranker_api.min_score is optional. If set, it keeps chunks with a raw reranker score greater than or equal to the finite numeric floor. Scores are model-specific and are not probabilities; choose a floor using labeled queries. Without a floor, the reranker sorts all candidates. Without a reranker, this setting has no effect and hybrid search can still return unrelated neighbors. The -4 shown here was measured for the named local reranker on this corpus; it is not a general default. See the calibration report and the 50 reusable questions. Once a clean embedding batch is indexed, search can return those memories while the remaining index builds. Hybrid results include partial: true until the index catches up. A configured endpoint failure remains visible; search never silently substitutes exact search or skips a configured reranker.

The implementation uses Symfony AI's Vektor bridge for persistent HNSW vectors, its SQLite Store for FTS5 BM25, and CombinedStore for reciprocal-rank fusion. PHP needs mbstring and pdo_sqlite with SQLite FTS5 support. The extension pins the tested store packages and Vektor version in its Composer requirements. It retrieves at most 100 chunks from each store, fuses at most 200 candidates, optionally reranks them, and collapses them to source memories before applying the existing result limit. No raw ranking scores are returned. truncated is true when either the candidate budget or result limit is reached. Date-constrained or partial queries overfetch at most 500 candidates per store, filter against current memories, and retain at most 100 per ranked list. Returned dates remain correct, but matches outside the bounded candidate pool can be omitted. Exhausting that pool sets truncated, even with zero surviving hits.

The tool name and arguments remain unchanged. Its description, query guidance, and limit description switch between exact and hybrid capabilities. Reranker configuration does not change that guidance. recall uses the same canonical memory IDs and source session IDs in both modes.

The full-corpus benchmark records backfill cost, retrieval quality, bounded date filtering, and negative-query limitations.

Index lifecycle and privacy

The extension schedules indexing through extension_agent at session start and after successful observation and reflection jobs. Each worker processes one bounded batch and schedules a continuation until complete. SQLite records progress; restarting a worker does not repeat completed clean batches. Workers can serve different projects sequentially, with per-operation Vektor setup.

Canonical observations and reflections remain in the configured OM SQLite file. om_semantic_document and its FTS table hold derived chunk text. The sibling <database-path>.semantic/vektor/ directory holds vectors, chunk text metadata, and graph files. These are Composer dependencies, not a native SQLite extension or external service.

A durable dirty marker precedes writes to the two stores. An interrupted write forces rebuilding derived storage at the next indexing job. Deletions, changed chunks, changed embedding models, and missing vector files also cause rebuilding. Vektor soft deletes are deliberately not used: their fixed candidate buffer can return no results despite live documents. Search marks clean incomplete or stale results as partial: true. It checks chunk IDs against current source text before ranking, so deleted or edited memories do not appear from obsolete chunks. New memories may be absent until their chunks are indexed. Dirty, incompatible, uninitialized, or busy indexes still return an error. Missing storage or explicit corruption invalidates the index; transient read failures do not discard embeddings. Configured endpoint failures return visible errors without fallback results. A later session start can restart failed indexing. Query HTTP calls do not hold the index lock. The source/index snapshot is revalidated after embedding; reranking uses materialized hits after releasing the read lock.

index_building includes indexed_count and source_count, both in memory units. The first counts current source memories represented by at least one indexed chunk, not fully indexed memories or search readiness. Dirty or incompatible indexes report zero. Counts reuse the loaded source snapshot and stored parent metadata rather than rescanning and rechunking the corpus.

The embedding endpoint receives memory chunks and prefixed search queries. The reranker receives queries and bounded candidate text. Only configure trusted endpoints. Logs record failure stages and correlation fields, not memory text, queries, vectors, response bodies, or chained HTTP exceptions. Derived files have the same privacy requirements as canonical memory and remain on disk when semantic retrieval is disabled. Deleting canonical rows prevents stale search immediately; the next successful indexing job removes their derived copies.

To rebuild a damaged index, stop indexing for that project, remove only its <database-path>.semantic/ directory, and start a session to schedule rebuilding. Do not remove the canonical database to repair derived storage.

Generation model

One top-level observational_memory.model is shared by Observer, Reflector, and Dropper. Thinking levels are not configured; provider defaults apply. Observer uses maxToolCalls=6 to allow correction rounds while bounding accumulated context; Reflector and Dropper retain the Pi-mapped maxToolCalls=16 cap.


All versions of hatfield-ext-observational-memory with dependencies

PHP Build Version
Package Version
Requires php Version >=8.5
ext-mbstring Version *
ext-pdo_sqlite Version *
centamiv/vektor Version 2.0.2
doctrine/dbal Version ^4.3
helgesverre/toon Version ^3.1
ineersa/hatfield-extension-api Version @dev
psr/log Version ^3.0
symfony/ai-generic-platform Version ^0.14
symfony/ai-platform Version ^0.14
symfony/ai-sqlite-store Version ^0.14
symfony/ai-store Version ^0.14
symfony/ai-vektor-store Version ^0.14
symfony/clock Version ^8.0
symfony/filesystem Version ^8.0
symfony/http-client Version ^8.0
symfony/lock Version ^8.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package ineersa/hatfield-ext-observational-memory contains the following files

Loading the files please wait ...