npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

aiga-js

v0.1.0

Published

A compact compiler-runtime for a task-oriented DSL for AI generation and automation.

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

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:

  1. Parser
    Reads the DSL source and produces an AST.

  2. Compiler
    Resolves symbols, validates builtins, performs strict checks, infers units, lowers expressions to opcodes, and emits an executable artifact.

  3. Runtime
    Executes compiled artifacts only. It includes a compact VM, effect scheduler, trace system, budget engine, timeout support, and streaming support.

  4. Builtin registry
    Provides the standard library and lazy activation for namespaces like math, ai, rag, eval, stream, http, and ml.

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 cache

Installation

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 Cost

This is optional in spirit, but recommended.

Properties

Properties define external inputs.

Property syntax

name of source in type = default

Only 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 km

What 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 = 400

Use 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 + b

Steps 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 > 0

Use 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:

  • Types
  • Capabilities
  • Budgets
  • Policies
  • Metadata

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:
answer

Expressions

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
null

Arrays

["a", "b", "c"]

Objects

{
  query: query,
  top_k: 5
}

Unary operators

-value
+value
!flag

Binary 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 || b

Member access

result.score
user.name

Index 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 usd

What 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:
eta

Invalid example

Task: Invalid
Properties:
distance of distance in km
speed of speed in km/h

Steps:
bad = distance + speed

Formula:
bad

The 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:

  • ai
  • eval
  • rag
  • ml

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:
tokens

Training progress example

Task: Fine Tune with Progress
Steps:
job = ml.fine_tune("base-model", { dataset: "train.jsonl" }, { epochs: 2 })
progress = stream.progress(job)

Formula:
progress

Error 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:
greeting
const 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:
answer

5. 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:
final

10. 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