Manifest reference
pack.ael will be the manifest of AEL, the Agent Engineering Language: the one file that says which packages a project, or one folder of it, uses. It will be a declarative record, never code. It will have no expressions, no includes and no scripts, and nothing in it will run. # comments will be allowed. Using packages explains how manifests and folder scopes will work together.
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.
Top-level fields
pack {
schema = 1;
dependencies = [
{ name = "server/http"; version = "^1.2.0"; kind = "runtime";
source = { kind = "registry"; };
features = []; targets = []; capabilities = ["net.listen"];
publisher = "openeng"; }
];
}
| Field | Required | Meaning |
|---|---|---|
schema | Yes | The format version: 1. |
dependencies | Yes | The packages this scope uses. [] for none. |
toolchain | No | The AEL toolchain versions the project accepts, written like a version requirement. It will be checked before anything is resolved. |
registries | No | Package registries and their publishers. The official registry will be the default and will need no entry. |
Unknown and repeated fields will be refused. The project's name, description and settings will belong in metadata.ael, never in pack.ael.
Dependency fields
Every dependency will name each of these fields, even when a list is empty:
| Field | Meaning |
|---|---|
name | The package name, such as "server/http". See Names and aliases. |
version | A version requirement, such as "^1.2.0". |
kind | "runtime", "build" or "development". See Kinds. |
source | Where the package file comes from. See Sources. |
features | The package features you ask for, by name. [] for none. |
targets | The targets this dependency applies to. [] for all of the package's targets. |
capabilities | The permissions the package asks for, such as "net.listen". [] for none. |
publisher | "openeng" for official packages; your own publisher name for private ones. |
alias | Optional: a local name for the package in your source. |
Version requirements
| Requirement | Accepts | Example |
|---|---|---|
=M.m.p | Exactly that version. | "=1.2.3" |
^M.m.p | Compatible versions: the same major version from 1 up; the same minor version while the major is 0; only that version for 0.0.p. | "^1.2.3" accepts 1.2.3 up to, not including, 2.0.0 |
~M.m.p | Patch updates within the same minor version. | "~1.2.3" accepts 1.2.3 up to, not including, 1.3.0 |
>=A <B | A range with both bounds. | ">=1.2.0 <2.0.0" |
- There will be no wildcards, no "or" and no requirement without an operator. Numbers will have no leading zeros, and each will be at most 2,147,483,647. Versions will compare number by number, never as text.
- A pre-release, such as
1.3.0-rc.1, will be chosen only when you name it exactly with=. Build metadata after a+will be refused. - Adding, updating and locking will choose the highest version that fits. Installing and building will never choose again: they will use the lock file.
- One scope will use one version of each package.
Sources
kind | Fields | For |
|---|---|---|
"registry" | origin, optional; it defaults to https://pack.ael.openeng.ai | Official packages from the official registry. |
"https" | url and digest | A private package file at an https address that never changes. |
"local" | path and digest | A private package file kept inside the project. |
digest will be the file's fingerprint: sha256: followed by 64 lower-case hex digits. There will be no source that points at code to be built: every source will be a built package file. Private packages gives the rules for addresses and paths.
Kinds
"runtime": part of your program."build": an explicit input for your builds that never becomes part of your program. It will never run inside the compiler, as an install script or by itself during a build, which runs no package code. What a build dependency will provide, and how you will use one, will be described when the manifest format is final."development": used for tests and development only. It will never reach your program unless it is also declared as a runtime dependency.
Features and targets
- A package will have no default features: you will get exactly the features you list. An unknown feature will be refused.
- When two packages in one scope ask for different features of a shared package, it will get the features that were explicitly requested, combined. Adding or updating will show any dependencies and capabilities that this brings.
targetswill list exact target names; see Planned targets. A dependency limited to other targets will stay in the lock file but be left out of builds for your target.
Capabilities and publishers
capabilitieswill be a request, never a grant. Your deployment will decide what a program may actually do, and a package will still receive only what your code passes to it. See Effects and capabilities.publisherwill have to match the publisher the package itself records. Only official packages from the official registry will carry"openeng".
Names and aliases
- Package names will be lower case and slash-separated, such as
server/httporacme/billing. Each part will start with a letter and continue with letters, digits,_or-. A name will be at most 128 characters. - AEL will never guess at a misspelled name or substitute a similar-looking one: an unknown name will be an error.
aliaswill be an AEL identifier. It will not be allowed to be a keyword,_orprint, and two aliases in one scope will not be allowed to differ only in letter case.
Limits
- Every
pack.aelwill stay within the limits of every source file: at most 5,000 bytes and at most 5,000 lines. Split a long list of dependencies into folder scopes. See Limits. - The planned resolution limits for one scope are 1,024 packages and 8,192 dependency links, with no chain of dependencies more than 64 links long. Going over will be an error, never a partial result.
- A dependency cycle will be refused, and the error will name the whole cycle.
The lock file
pack.lock will be generated beside each pack.ael by ael pack add, ael pack update and ael pack lock (command names may change before launch), and read by ael pack install --locked. It will record:
- the exact version, origin, publisher and fingerprint of every package in the scope, direct or not;
- how the packages depend on each other;
- the features and targets chosen;
- which manifest it belongs to.
With it, builds will repeat, even offline, and nothing will download when an app starts. Never edit it by hand: if it no longer matches its manifest, ael pack install --locked will stop instead of changing it. It will never hold secrets, access tokens or absolute paths.
The data of a manifest and of a lock file each have a published JSON Schema, still a draft: Package manifest and Package lock file. The manifest schema describes the parsed data; pack.ael itself will always be written as shown above.