Browse the documentation

Preview documentation for AEL Beta 0.0.1 — launching soon

Using packages

A project in AEL, the Agent Engineering Language, will declare the packages it uses in pack.ael, and AEL will record exactly what it resolved in pack.lock. Your source will name the parts of a package it uses, and only those parts will reach your program.

Status

Planned for AEL Beta 0.0.1. AEL is not available yet.

Package names on this page are preview naming and may change before launch.

The manifest

Every project will have a pack.ael at its root, even when it uses no packages. This is a complete manifest:

Preview syntax — may change before launch
pack { schema = 1; dependencies = []; }

A project that serves HTTP will add the official server/http package:

Preview syntax — may change before launch
pack {
    schema = 1;
    dependencies = [
        { name = "server/http"; version = "^1.2.0"; kind = "runtime";
          source = { kind = "registry"; };
          features = []; targets = []; capabilities = ["net.listen"];
          publisher = "openeng"; }
    ];
}

Each dependency will name every field explicitly, so a manifest reads the same to everyone. A manifest will be a declaration, never code: nothing in it will run. The Manifest reference describes every field.

Folder scopes

The root pack.ael will cover the whole project. Any folder will be able to have its own pack.ael, which will cover that folder and the folders below it:

Preview syntax — may change before launch
support/
  main.ael
  pack.ael          # server/http for the whole project
  pack.lock
  metadata.ael
  .package/         # generated: the root scope's installed packages
  api/
    pack.ael        # its own version of server/http, for api/ and below
    pack.lock
    .package/
  jobs/             # no manifest: uses the root's server/http
  • The nearest manifest that declares a package will win. A file in api/ will use the version in api/pack.ael; a file in jobs/ will use the root's.
  • A folder's manifest will add; it will never hide. Packages declared further up will stay available unless the folder declares the same package itself.
  • Siblings and sub-folders will never supply packages. A file in the root will not be able to use a package declared only in api/pack.ael, and jobs/ will never see api/'s packages.
  • No silent fallback. If the nearest declaration does not fit, the check will fail; AEL will never fall back to a version further up that happens to fit.
  • Each manifest will have its own lock file and installed packages, beside it: pack.lock and .package/. A scope with no packages will need no .package/.

Two folders will be able to use different versions of one package only when those versions can work side by side in one program; when they cannot, AEL will report the conflict instead of picking one.

Managing packages

ael pack (command names may change before launch) will manage a project's packages:

CommandWill
ael pack add <name>[@<version>]Add a new package to a manifest, resolve it, install it and write the lock file, all at once.
ael pack installInstall exactly what pack.ael and pack.lock already say, changing no version. --locked will refuse to change the lock file; --offline will use verified local copies only.
ael pack update <name>Move a package to another version its requirement allows, and show what else changes.
ael pack remove <name>Remove a package, keeping the packages that others still need.
ael pack lockResolve the manifest and write the lock file, without installing anything.
ael pack listList the packages that are declared, installed and actually used.
ael pack why <name>Explain why a package is in the project, and through which path.
ael pack verifyCheck the installed packages against the lock file.

add will be for a package the project does not use yet; install will set up what is already declared and locked, such as on a new machine. add, install, update, remove, lock and list will take --scope <folder> to choose which folder's manifest they act on; without it, they will use the manifest that covers the folder you are in. Adding with --scope to a folder that has no pack.ael yet will be able to create one there. Every change will report the scope it acted on, and every command will take --json for machine-readable output.

Preview syntax — may change before launch
ael pack add server/http@1.2.3
ael pack add math/linalg --scope src/analysis
ael pack install --locked
ael pack update server/http
ael pack remove server/http

Every change will be atomic. The manifest, the lock file and the installed packages will change together, and an interrupted change will leave the complete old state or the complete new one, never a mix. Adding or updating a package will show the dependencies and capabilities it brings before anything changes.

Removing a package will never edit your source. If a file still refers to the package, the next check will fail and name the reference, so you can remove it deliberately. If you remove a package from a folder's own manifest and a manifest further up still declares it, the files of that folder will then use that one, and the command will tell you so.

Using a package in your source

A file will name the package exports it uses in its header, before its first declaration:

Preview syntax — may change before launch
# src/api/billing.agent.ael
refer server/http select get;

@get
agent billing(input: Request) -> Decision {
    # The selected hook export is attached to this agent.
}

This example shows only how a file selects an export and attaches it, here the hook get. It is not how you serve an HTTP route: routes will live in a .routes.ael file that main mounts, as Services and APIs shows.

  • refer will name the package; select will name the exports this file uses, separated by commas.
  • Every selected export will have to be used. A call, a value reference or a hook attachment in code that can run will count. A comment, a string, a helper nobody calls or code after a return will not. Selecting get, put and using only get will fail the check.
  • A package will never add names to your folders. Its helpers will never be visible, and its exported functions only where you select them by name.
  • A package that is installed but never selected will be allowed; the reference map will report it as unused.

Only what you use will ship

A build will keep only what your program can reach from main. A console agent will need no server: add server/http and declare routes to make it a REST API, or remove them to go back to console-only; Services and APIs shows both. An HTTP-only app will carry no gRPC or WebSocket code, and a GET-only API no POST handlers.

ael refmap will show what references what, for the whole project, one folder or one file, and list unused code and packages.

The lock file and offline builds

  • pack.lock will record the exact version, origin and fingerprint of every package a scope uses, its dependencies, and the features and targets chosen. It will be generated; never edit it by hand.
  • Keep pack.lock with your source files, and leave .package/ out: ael pack install --locked will recreate it on any machine from the lock file.
  • ael pack install --locked --offline will not use the network: it will install from verified local copies and name any package file it is missing.
  • Exporting for offline builds covers machines without a network connection, and Pruning the package cache clearing cached packages that no project uses.
  • Checking, compiling and building will use only the locked, installed packages: they will never contact the registry, change a version or install anything. Nothing will download when an app starts. A missing package will be an error that tells you to run ael pack install.