@adaas/a-frame
v0.1.18
Published
A-frame is index build engine for A-Concept ecosystem. It provides a way to build index structures for A-Concept basics
Maintainers
Readme
A-Frame
Index build engine and AI-knowledge runtime for the A-Concept ecosystem.
Table of Contents
- Overview
- What A-Frame Does
- Getting Started
- Account & Server Setup
- Environment Variables
- CLI Reference
- Programmatic Usage
- Storage Layout
- Examples
- License
Overview
A-Frame is the index build engine of the A-Concept ecosystem. It turns
the decorated A_Component / A_Entity / A_Fragment definitions that live
in your TypeScript codebase into a queryable, embedded, and (optionally)
encrypted index — and runs the runtime side of retrieval-augmented generation
(RAG) on top of that index.
It is built on the same primitives as @adaas/a-concept:
every capability is exposed as a A_Component, A_Container, A_Entity or
A_Fragment. There are no loose helpers, no static singletons, no global
event buses — A-Frame is itself a concept you compose with your own.
The library ships as three surfaces:
@adaas/a-frame— runtime entrypoint (Node + browser). Imports asA_Frameand plugs into yourA_Conceptto give your app embedding, vector search, completion and dynamic knowledge.@adaas/a-frame/core//index//segment//schema/ … — fine-grained sub-exports for tree-shaken consumers.a-frame— globally installable CLI (bin/a-frame) for building knowledge bases, packaging browser bundles, and exploring storage.
What A-Frame Does
| Capability | Where it lives | Used for |
|---|---|---|
| Discover & embed definitions | A_FrameIndex + A_Frame.Define(...) decorator | Build a semantic index of every component you've registered so the LLM can pick the right one by description. |
| Dynamic knowledge (RAG) | A_FrameDynamicKnowledge + A_FrameKnowledgeRecord + A_FrameSegment | Persist long-form text, segment it, embed the segments, then answer questions via keyword / vector / hybrid search. |
| Schema-driven extraction | A_FrameSchema + A_FrameCompletion | Ask the LLM for a structured JSON object matching a typed schema (used by --knowledge to enrich records). |
| Encrypted browser bundle | A_FrameBundleBuilder | Package the contents of .aframe/ into a single decryptable artifact your front-end can ship. |
| CLI tooling | bin/a-frame (src/concept.ts) | --embed, --knowledge, --bundle, --query, --explore. |
The decorators register definitions; A_FRAME_SYNC=true lets concept.load()
embed them against the configured server and cache the result under
A_FRAME_STORAGE_DIR. Subsequent runs reuse the cache and skip the network
calls.
Getting Started
Install the package:
npm install @adaas/a-frame @adaas/a-conceptCompose it with your concept:
import { A_Concept, A_Container } from '@adaas/a-concept';
import { A_Frame } from '@adaas/a-frame/core';
import { config as loadDotenv } from 'dotenv';
loadDotenv();
const concept = new A_Concept({
name: 'MyApp',
components: [A_Frame],
containers: [
new A_Container({
name: 'AppContainer',
components: [/* your @A_Frame.Define()-decorated components */],
}),
],
});
await concept.load(); // discovers, embeds (when A_FRAME_SYNC=true) and caches
await concept.start(); // your app runsInstall the CLI globally (optional):
npm install -g @adaas/a-frame
a-frame --helpAccount & Server Setup
A-Frame embedding, completion, and credential exchange require an A-Frame Server instance. You can either:
- Use the managed service — sign up at https://adaas.org and create an API key from the dashboard. The key and the matching encryption key are shown once at creation time.
- Self-host — run the open-source server from
@adaas/a-server. See its README for Docker and bare-metal instructions. The default local URL ishttp://localhost:3663.
Once you have an API key, copy .env.example to .env and fill in the
values:
cp .env.example .envOffline / keyword-only workflows are supported by setting
A_FRAME_SYNC=false— no server is required in that mode.
Environment Variables
A-Frame reads its configuration via the A_FrameEnv fragment. All variables
are resolved from process.env; a .env file at the project root is loaded
automatically by the CLI bootstrap.
| Variable | Required | Default | Purpose |
|---|---|---|---|
| A_FRAME_SERVER_URL | Yes (when A_FRAME_SYNC=true) | http://localhost:3663 | Base URL of the A-Frame server used for embedding, completion, and credential exchange. |
| A_FRAME_SERVER_API_KEY | Yes (when A_FRAME_SYNC=true) | — | API key issued by the A-Frame server. Used to authenticate every request. |
| A_FRAME_SERVER_ENCRYPTION_KEY | Optional | retrieved from server | Base64 symmetric key used to encrypt/decrypt .aframe* storage files. Normally fetched automatically via GET /api/credentials/me — only set this manually for air-gapped builds. |
| A_FRAME_SYNC | No | true | Set to false to disable all network calls (no embedding, no completion). Useful for offline keyword-only search. |
| A_FRAME_STORAGE_DIR | No | .aframe | Directory where namespace, definition and knowledge files are written. Created on demand. |
| A_FRAME_STORAGE_PATTERN | No | node_modules/**/.aframe | Glob(s) scanned at startup for additional read-only .aframe directories (lets npm packages ship pre-built indexes). Set to '' to disable. |
| A_FRAME_REQUEST_TIMEOUT | No | 120000 | Per-request HTTP timeout in milliseconds (AI inference can be slow). |
| A_FRAME_TOKEN | No | — | Pre-issued bearer token (alternative to API-key flow for short-lived sessions). |
| A_FRAME_ENV_FILE | No | ./.env | Override the path of the .env file loaded by the CLI bootstrap. |
Minimal .env:
A_FRAME_SERVER_URL=https://api.adaas.org
A_FRAME_SERVER_API_KEY=ek_your_api_key_here
A_FRAME_STORAGE_DIR=.aframeCLI Reference
The CLI is registered as a-frame (or run via npm run cli).
Run a-frame --help for the full screen; the commands are:
| Command | Summary |
|---|---|
| a-frame --embed <target> | Discover files containing A_Frame.* decorators, import them, and embed the resulting definitions. |
| a-frame --knowledge <sourceDir> --name <kb> | Walk <sourceDir>, treat every file matching --include as a document, segment + embed, and write <kb>.aframek to --out (defaults to A_FRAME_STORAGE_DIR). Existing records with a matching FNV-1a hash are kept untouched so embeddings survive rebuilds. |
| a-frame --query <path> | Open an interactive REPL over a .aframek file. Bare text is a search query; --completion answers with an LLM call grounded in the top hits (RAG). |
| a-frame --bundle [out] | Decrypt every .aframe* file in A_FRAME_STORAGE_DIR and package them into a single browser bundle (.ts or .json). |
| a-frame --explore [path] | List every A-Frame file under <path> (defaults to cwd) with its type, size and relative path. |
| a-frame --version / --help | Standard. Per-command help is available via a-frame <cmd> --help. |
Examples:
# Embed everything under src/
a-frame --embed src/
# Build a knowledge base from a docs folder
a-frame --knowledge ./docs --name project-knowledge \
--segment-length 500 --segment-unit chars --include .md,.mdx
# Ask questions about the resulting knowledge base
a-frame --query ./.aframe/project-knowledge.aframek --completion
# Inspect the storage directory
a-frame --explore ./.aframe
# Package for the browser
a-frame --bundle dist/a-frame-bundle.tsProgrammatic Usage
Decorate components for the index
import { A_Component } from '@adaas/a-concept';
import { A_Frame } from '@adaas/a-frame/core';
@A_Frame.Define({
description: 'A bar chart that compares numerical values across named categories.',
metadata: { params: { data: 'category:number lines, one per row' } },
})
export class BarChart extends A_Component {
static render(p: { data: string }): void { /* … */ }
}Pick a component by intent
import { A_FrameIndex } from '@adaas/a-frame/index';
const index = A_Context.scope(this).resolve(A_FrameIndex);
const [hit] = await index.search('show comparative numbers per category', { topK: 1 });
hit.component.render({ data: 'Cats: 12\nDogs: 8' });Hybrid search + RAG completion on a knowledge base
import { A_FrameDynamicKnowledge } from '@adaas/a-frame/dynamic-knowledge';
import { A_FrameCompletion } from '@adaas/a-frame/completion';
const kb = await A_FrameDynamicKnowledge.load({ name: 'project-knowledge' });
const hits = await kb.search('how do I configure storage?', { topK: 5, mode: 'hybrid' });
const answer = await new A_FrameCompletion().ask({
prompt: 'Answer using only the context below.',
context: hits.map(h => h.content).join('\n---\n'),
});See examples/dynamic-knowledge/main.ts
and examples/cli/knowledge/main.ts for the
full RAG-REPL pipeline.
Storage Layout
A-Frame uses four file extensions under A_FRAME_STORAGE_DIR:
| Extension | Contents |
|---|---|
| .aframen | Single index of all registered namespaces (one per storage dir, filename is literally .aframen). |
| .aframed | One file per namespace, holding the binary-encoded definitions registered under it. Filename is <namespaceId>.aframed. |
| .aframek | One file per dynamic-knowledge base, holding records + segments + embeddings. Filename is <kbName>.aframek. |
| .aframe | Reserved base extension (legacy / internal). |
All payloads are encrypted with A_FRAME_SERVER_ENCRYPTION_KEY when written
by the runtime; the --bundle command produces a decrypted artifact for the
browser. Use a-frame --explore to inspect a storage directory at a glance.
Examples
The examples/ folder is wired into npm scripts:
npm run example:dynamic-knowledge # in-process RAG REPL with seeded knowledge
npm run example:cli-knowledge # CLI → REPL pipeline (spawns a-frame --knowledge)
npm run example:article # dynamic article generator using the index
npm run example:structure # picks the right SaaS structure for a prompt
npm run example:feature # picks the right feature implementation for a promptEach example has its own main.ts with inline usage notes and the env vars
it understands.
License
Apache-2.0 © ADAAS YAZILIM LİMİTED ŞİRKETİ
