aiga-js
v0.1.0
Published
A compact compiler-runtime for a task-oriented DSL for AI generation and automation.
Maintainers
Readme
AIGA.js
AIGA.js is a compact compiler-runtime for a task-oriented DSL built for AI generation and automation.
It lets you define tasks declaratively, compile them into executable artifacts, and run them with a small runtime that supports:
- expressions and formulas
- steps and conditions
- strict symbol checking
- unit-aware arithmetic
- built-in function namespaces
- AI/provider/tool calls
- RAG workflows
- evaluation workflows
- streaming workflows
- agent workflows
- safety and policy hooks
- budgets, timeouts, and tracing
AIGA.js is designed around a simple idea:
Write a task, compile it once, run it many times.
Table of contents
- Why AIGA.js
- Current design
- Project structure
- Quick start
- The DSL at a glance
- Sections
- Expressions
- Units
- Public API
- Compile options
- Runtime options
- Builtin namespaces
- Providers, tools, and policies
- Artifacts and inspection
- Streaming and realtime usage
- Error handling
- Examples
- 1. Basic calculation task
- 2. Strict inputs and defaults
- 3. Unit-aware ETA calculation
- 4. Prompt assembly + AI generation
- 5. Token budgeting
- 6. Simple RAG flow
- 7. Evaluation with judge-style scoring
- 8. Realtime token streaming
- 9. Agent workflow
- 10. Safety and policy enforcement
- 11. File and HTTP automation
- 12. Training/fine-tuning orchestration
- Status and scope
Why AIGA.js
Most AI automation systems end up as a mix of prompts, ad hoc JavaScript, provider SDK calls, and runtime-specific glue.
AIGA.js gives that work a task language and a compiled execution model.
You describe:
- what inputs exist
- what constants exist
- what steps should run
- what conditions must hold
- what final formula should return
AIGA.js handles:
- parsing
- semantic compilation
- artifact generation
- strict validation
- runtime execution
- effect scheduling
- streaming
- budgets
- policy hooks
Current design
AIGA.js is intentionally small, but it is not a toy interpreter.
It is built around four layers:
Parser
Reads the DSL source and produces an AST.Compiler
Resolves symbols, validates builtins, performs strict checks, infers units, lowers expressions to opcodes, and emits an executable artifact.Runtime
Executes compiled artifacts only. It includes a compact VM, effect scheduler, trace system, budget engine, timeout support, and streaming support.Builtin registry
Provides the standard library and lazy activation for namespaces likemath,ai,rag,eval,stream,http, andml.
Project structure
parser.js # DSL parser
compile.js # semantic compiler + artifact builder
runtime.js # artifact runtime + VM + scheduler
builtins.js # builtin registry + namespace implementations
aiga.js # public API + host registries + compile cacheInstallation
npm install aiga-js
## Quick start
> The package name and npm publishing details are intentionally left open until the package is published.
### Example usage
```js
import { run } from "./alga-js";
const source = `
Task: Travel ETA
Properties:
distance of distance in km
speed of speed in km/h
Steps:
eta = distance / speed
Conditions:
distance > 0
speed > 0
Formula:
{
eta_hours: eta
}
`;
const result = await run(source, {
distance: { value: 120, unit: "km" },
speed: { value: 60, unit: "km/h" }
});
console.log(result);The DSL at a glance
AIGA.js uses a section-based DSL.
Minimal example
Task: Area of Rectangle
Properties:
width of width in m
height of height in m
Steps:
area = width * height
Conditions:
width > 0
height > 0
Formula:
{
area
}Sections
Task
Defines the title of the task.
Task: Calculate Shipping CostThis is optional in spirit, but recommended.
Properties
Properties define external inputs.
Property syntax
name of source in type = defaultOnly the name is essential; source, type, and default are optional depending on the line. Use clear names and prefer explicit types/units.
Example
Properties:
query of user_query in text
top_k of top_k in number = 5
distance of route_distance in kmWhat properties are for
Use properties for:
- user input
- external data
- runtime-provided values
- request payload fields
- task parameters
Constants
Constants define fixed values known at compile time or task-definition time.
Constants:
temperature = 0.2
max_tokens = 400Use constants for:
- prompt parameters
- thresholds
- fixed weights
- default strategies
- feature toggles
Steps
Steps are named assignments executed as part of the task plan.
Steps:
a = 10
b = 20
total = a + bSteps can reference:
- properties
- constants
- earlier steps
- builtin functions
- provider-backed operations
- arrays and objects
Use steps for:
- transformations
- data prep
- prompt construction
- retrieval
- evaluation
- orchestration
Conditions
Conditions are guards that must evaluate truthy.
Conditions:
query != ""
top_k > 0
budget > 0Use conditions for:
- input validation
- preconditions
- post-step quality checks
- fail-fast control
Formula
Formula defines the final output of the task.
Formula:
{
answer,
score,
citations
}The formula can be:
- a literal
- an object
- an array
- a scalar
- a step reference
- any valid expression
Optional sections
AIGA.js also supports these optional sections:
TypesCapabilitiesBudgetsPoliciesMetadata
Example
Task: Controlled Answering
Properties:
query of query in text
Budgets:
tokens = 1000
usd = 0.20
ms = 5000
Policies:
["pii-guard", "allow-only-approved-models"]
Metadata:
{
owner: "team-search",
domain: "support"
}
Steps:
answer = ai.generate(prompt.answer(query))
Formula:
answerExpressions
AIGA.js supports compact expressions with:
- string literals
- number literals
true,false,null- identifiers
- arrays
- objects
- unary operators
- binary operators
- member access
- index access
- function calls
Literals
42
"hello"
true
nullArrays
["a", "b", "c"]Objects
{
query: query,
top_k: 5
}Unary operators
-value
+value
!flagBinary operators
a + b
a - b
a * b
a / b
a % b
a ^ b
a == b
a != b
a > b
a >= b
a < b
a <= b
a && b
a || bMember access
result.score
user.nameIndex access
items[0]
scores[i]Function calls
Builtin calls use namespace-style member access:
math.sum(values)
string.upper(name)
rag.retrieve(index, query, 5)
ai.generate(prompt)Units
AIGA.js supports lightweight unit-aware compilation.
You can declare a property with a unit-like type:
Properties:
distance of distance in km
speed of speed in km/h
price of price in usdWhat unit support does
It allows the compiler to:
- attach units to inputs and derived values
- propagate obvious units through multiplication and division
- reject obvious invalid
+and-operations between incompatible units
Valid example
Task: ETA
Properties:
distance of distance in km
speed of speed in km/h
Steps:
eta = distance / speed
Formula:
etaInvalid example
Task: Invalid
Properties:
distance of distance in km
speed of speed in km/h
Steps:
bad = distance + speed
Formula:
badThe second task should fail at compile time because + requires matching units.
Public API
compile
Compiles source into an executable artifact.
import { compile } from "./alga-js";
const artifact = compile(source);Use compile when you want:
- compile-once/run-many behavior
- inspection
- artifact caching
- pre-validation
run
Compiles if needed, then runs the task and returns the final result.
import { run } from "./alga-js";
const result = await run(source, { x: 10, y: 20 });stream
Compiles if needed, then runs the task in a streaming-oriented mode.
import { stream } from "./alga-js";
const output = await stream(source, { query: "Explain RAG" });
for await (const item of output) {
console.log(item);
}Use stream when your task produces:
- token streams
- progress streams
- merged live streams
- agent loops
- long-running outputs
inspect
Inspects either source or an artifact.
import { inspect } from "./alga-js";
const info = await inspect(source, { includeArtifact: true });
console.log(info);Inspection is useful for:
- builtins used
- slot layout
- compile stats
- graph shape
- step order
- constant order
registerProvider
Registers a provider adapter.
import { registerProvider } from "./alga-js";
registerProvider("ai", {
async generate(input, opts, ctx) {
return {
text: `Generated: ${JSON.stringify(input)}`
};
}
});Providers are used by namespaces such as:
aievalragml
registerTool
Registers a callable tool.
import { registerTool } from "./alga-js";
registerTool("weather.lookup", async ({ city }) => {
return { city, temp_c: 27 };
});Tools can then be used through provider or agent workflows.
registerPolicy
Registers a policy hook.
import { registerPolicy } from "./alga-js";
registerPolicy("require-query", async (payload) => {
if (payload.phase === "before" && payload.args?.[0] === "") {
return { allow: false, reason: "empty query" };
}
return { allow: true };
});Policies can:
- allow
- deny
- return structured responses
- throw indirectly through denial
- run before and after effect calls
Compile options
allowImplicitInputs
Default behavior should be treated as strict: unknown identifiers should fail compilation unless this compatibility option is enabled.
const artifact = compile(source, {
allowImplicitInputs: true
});Use this only for legacy or exploratory workflows.
allowedInputs
Lets you whitelist names that may be treated as runtime inputs even if not declared in Properties.
const artifact = compile(source, {
allowedInputs: ["query", "budget"]
});cache
Disable compile cache when needed.
const artifact = compile(source, {
cache: false
});cacheSize
Controls compile cache size.
const artifact = compile(source, {
cacheSize: 64
});cacheSalt / cacheKey
Useful if you want to force cache separation.
const artifact = compile(source, {
cacheSalt: "experiment-a"
});Runtime options
trace
Controls trace verbosity.
Supported values:
"off""basic""verbose"
await run(source, inputs, { trace: "verbose" });timeoutMs / timeout
Sets runtime deadline.
await run(source, inputs, {
timeoutMs: 3000
});budget
Sets runtime budget limits.
await run(source, inputs, {
budget: {
tokens: 2000,
usd: 0.50,
calls: 10,
ms: 5000
}
});maxConcurrency / concurrency
Controls concurrent effect dispatch.
await run(source, inputs, {
maxConcurrency: 2
});cacheEffects
Enables runtime effect caching for cacheable non-stream effects.
await run(source, inputs, {
cacheEffects: true
});effectTimeoutMs
Sets per-effect timeout.
await run(source, inputs, {
effectTimeoutMs: 1500
});signal
Supports cancellation with AbortController.
const controller = new AbortController();
const promise = run(source, inputs, {
signal: controller.signal
});
controller.abort();
await promise;Builtin namespaces
AIGA.js organizes builtins by namespace.
math
Numeric operations.
Typical use:
- arithmetic
- aggregates
- clamping
- statistics
Example
Steps:
subtotal = math.add(price, tax)
avg = math.mean(scores)
bounded = math.clamp(score, 0, 1)string
String processing.
Example
Steps:
title = string.upper(name)
slug = string.replace(string.lower(name), " ", "-")
summary = string.slice(text, 0, 200)array
Array transforms and utilities.
Example
Steps:
top3 = array.slice(items, 0, 3)
chunks = array.chunk(items, 10)
unique_tags = array.unique(tags)object
Object manipulation helpers.
Example
Steps:
merged = object.merge(base, overrides)
owner = object.get(config, "owner")
keys = object.keys(settings)logic
Logical helpers and control-style helpers.
Example
Steps:
status = logic.if_else(score > 0.8, "good", "review")
safe_query = logic.coalesce(query, "default query")unit
Unit-aware helpers.
Example
Steps:
price = unit.value(10, "usd")
km = unit.convert(distance, "km")
display = unit.format(price)prompt
Prompt and message construction.
Example
Steps:
sys = prompt.system("You are a precise assistant.")
usr = prompt.user(query)
msgs = prompt.messages(sys, usr)
final_prompt = prompt.answer(query, hits)token
Token estimation and budget-aware prompt handling.
Example
Steps:
estimated = token.estimate(final_prompt)
trimmed = token.trim_to_budget(final_prompt, 1500)ai
Provider-backed AI generation, chat, embedding, moderation, extraction, and classification.
Example
Steps:
answer = ai.generate({
prompt: final_prompt,
temperature: 0.2
})
label = ai.classify(text, ["safe", "unsafe"])
vector = ai.embed(text)rag
Retrieval-augmented generation helpers.
Example
Steps:
chunks = rag.chunk(documents, { size: 256, overlap: 0.15 })
index = rag.index(chunks)
hits = rag.retrieve(index, query, 5)
reranked = rag.rerank(hits, query)eval
Evaluation helpers for exact matching, similarity, score aggregation, and judge-style evaluation.
Example
Steps:
exact = eval.exact(answer, expected)
sim = eval.similarity(answer, expected)
judge = eval.judge(answer, { query, hits })stream
Streaming helpers. These are ideal for realtime UX.
Example
Steps:
events = stream.of("a", "b", "c")
mapped = stream.map(events, formatter)
limited = stream.take(events, 10)agent
Agent-style orchestration helpers.
Example
Steps:
plan = agent.plan({ query, tools: ["search", "calc"] })
result = agent.run({ query, plan })
final = agent.finish(result)safety
Safety and governance helpers.
Example
Steps:
check = safety.check(answer)
redacted = safety.redact(answer)http
HTTP automation helpers.
Example
Steps:
response = http.get("https://example.com/data")
posted = http.post("https://example.com/submit", payload)file
Filesystem-related helpers where available.
Example
Steps:
text = file.read("./notes.txt")
exists = file.exists("./notes.txt")ml
Training and model job orchestration helpers.
Example
Steps:
job = ml.train({
model: "tiny-model",
dataset: "dataset.jsonl"
})
status = ml.job_status(job)Providers, tools, and policies
These are the three main extension points.
Providers
Providers implement heavyweight or backend-specific behavior.
Good uses:
- AI model adapters
- embedding providers
- evaluation models
- remote RAG services
- training backends
Tools
Tools are domain-specific functions you want available to your workflows.
Good uses:
- CRM lookup
- weather lookup
- search
- pricing lookup
- business rules
Policies
Policies are runtime hooks for enforcement and governance.
Good uses:
- deny certain providers
- require metadata tags
- block risky prompts
- enforce PII rules
- apply cost controls
Artifacts and inspection
Compiling produces an artifact.
What an artifact contains conceptually
- source hash
- title
- constant pool
- slots
- slot metadata
- slot units
- compiled constants
- compiled steps
- pre-guards
- post-guards
- formula
- builtins used
- flags
- stats
- graph
- dependency-aware ordering
Inspecting a task
import { inspect } from "./alga-js";
const info = await inspect(source, { includeArtifact: true });
console.log(info.hash);
console.log(info.stats);
console.log(info.flags);
console.log(info.slots);
console.log(info.constant_order);
console.log(info.step_order);
console.log(info.graph);This is especially useful when you want to understand:
- which steps depend on which
- which builtins are involved
- whether the task has effects or streams
- how many slots/pool entries/nodes were emitted
Streaming and realtime usage
AIGA.js supports realtime-style workflows through AsyncIterable.
That means you can use streaming for:
- token output
- progress updates
- collected events
- long-running orchestration
Basic streaming example
import { stream } from "./alga-js";
const task = `
Task: Stream Example
Steps:
events = stream.of("hello", "from", "aiga")
Formula:
events
`;
const out = await stream(task);
for await (const item of out) {
console.log(item);
}Token-style generation example
Task: Streaming Answer
Properties:
query of query in text
Steps:
prompt_text = prompt.answer(query)
tokens = stream.tokens(ai.generate({ prompt: prompt_text }))
Formula:
tokensTraining progress example
Task: Fine Tune with Progress
Steps:
job = ml.fine_tune("base-model", { dataset: "train.jsonl" }, { epochs: 2 })
progress = stream.progress(job)
Formula:
progressError handling
AIGA.js uses structured runtime and compile errors.
Typical compile-time errors
- unknown identifier
- duplicate declarations
- invalid builtin arity
- unknown builtin operation
- invalid unit arithmetic
- unit conflict
- dependency cycles
Typical runtime errors
- budget exceeded
- policy denied
- timeout
- aborted
- invalid artifact
- builtin missing
- non-function call
- stack underflow
- opcode errors
Example
try {
await run(source, inputs, { timeoutMs: 100 });
} catch (err) {
console.error(err.name, err.code, err.message);
}Examples
1. Basic calculation task
Task: Sum Two Values
Properties:
a of a in number
b of b in number
Steps:
total = a + b
Formula:
{
total
}2. Strict inputs and defaults
Task: Greeting
Properties:
name of name in text = "World"
Steps:
greeting = string.concat("Hello, ", name)
Formula:
greetingconst result = await run(source, {});
// => "Hello, World"3. Unit-aware ETA calculation
Task: ETA
Properties:
distance of distance in km
speed of speed in km/h
Steps:
eta = distance / speed
Conditions:
distance > 0
speed > 0
Formula:
{
eta_hours: eta
}4. Prompt assembly + AI generation
Task: Answer Question
Properties:
query of query in text
context of context in text
Constants:
temperature = 0.2
Steps:
sys = prompt.system("Answer clearly and briefly.")
usr = prompt.user(query)
msgs = prompt.messages(sys, usr)
final_prompt = prompt.template("Context:\n{{context}}\n\nQuestion:\n{{query}}", {
context: context,
query: query
})
answer = ai.generate({
prompt: final_prompt,
temperature: temperature
})
Formula:
answer5. Token budgeting
Task: Budgeted Prompt
Properties:
query of query in text
Budgets:
tokens = 800
usd = 0.05
Steps:
base = prompt.answer(query)
estimated = token.estimate(base)
trimmed = token.trim_to_budget(base, 600)
answer = ai.generate(trimmed)
Formula:
{
estimated,
trimmed,
answer
}6. Simple RAG flow
Task: RAG Answer
Properties:
query of query in text
documents of documents in array
Constants:
top_k = 5
Steps:
chunks = rag.chunk(documents, { size: 256, overlap: 0.15 })
index = rag.index(chunks)
hits = rag.retrieve(index, query, top_k)
reranked = rag.rerank(hits, query)
answer = ai.generate(prompt.answer(query, reranked))
Formula:
{
hits: reranked,
answer
}7. Evaluation with judge-style scoring
Task: Evaluate Answer
Properties:
query of query in text
answer of answer in text
hits of hits in array
Steps:
judge = eval.judge(answer, { query, hits })
sim = eval.similarity(answer, query)
Formula:
{
judge,
similarity: sim
}8. Realtime token streaming
import { stream, registerProvider } from "./alga-js";
registerProvider("ai", {
async generate(input) {
async function* tokens() {
yield "AIGA";
yield " ";
yield "streams";
yield " ";
yield "tokens";
}
return tokens();
}
});
const task = `
Task: Stream Answer
Properties:
query of query in text
Steps:
answer = ai.generate({ prompt: query })
Formula:
answer
`;
const out = await stream(task, { query: "What is AIGA.js?" });
for await (const token of out) {
process.stdout.write(String(token));
}9. Agent workflow
Task: Agent Demo
Properties:
query of query in text
Steps:
plan = agent.plan({
query: query,
tools: ["search.lookup", "calc.eval"]
})
result = agent.run({
query: query,
plan: plan
})
final = agent.finish(result)
Formula:
final10. Safety and policy enforcement
import { run, registerPolicy } from "./alga-js";
registerPolicy("deny-empty-query", async (payload) => {
if (payload.phase === "before" && payload.args?.[0] === "") {
return { allow: false, reason: "empty_query" };
}
return { allow: true };
});
const task = `
Task: Safe Generate
Properties:
query of query in text
Policies:
["deny-empty-query"]
Steps:
answer = ai.generate(query)
Formula:
answer
`;
await run(task, { query: "" });11. File and HTTP automation
Task: Fetch and Save
Steps:
data = http.get("https://example.com/api")
saved = file.write("./out.json", data)
Formula:
{
data,
saved
}12. Training/fine-tuning orchestration
Task: Fine Tune
Properties:
dataset of dataset in text
Steps:
job = ml.fine_tune("base-model", dataset, {
epochs: 3,
learning_rate: 0.0001
})
status = ml.job_status(job)
Formula:
{
job,
status
}Status and scope
AIGA.js is already shaped like a real compiler-runtime:
- it parses a DSL into an AST
- compiles into artifacts
- runs artifacts through a VM + scheduler
- supports strict compilation
- supports units
- supports builtins by namespace
- supports streaming and policies
- supports provider/tool/policy registration
At the same time, some advanced namespaces are intentionally lightweight by default and become more powerful when you attach real providers or tools. That is by design.
AIGA.js is best understood as:
a compact task VM for AI generation and automation
License
MIT
