loopengine 0.1.22 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/bin/{package-manager.d.ts → ability-manager.d.ts} +39 -33
- package/dist/bin/{package-manager.js → ability-manager.js} +223 -98
- package/dist/bin/cli.js +22 -22
- package/dist/web/agents-config-page.js +15 -6
- package/dist/web/env-admin.d.ts +29 -10
- package/dist/web/env-admin.js +39 -21
- package/dist/web/http-tool-admin.d.ts +23 -12
- package/dist/web/http-tool-admin.js +60 -30
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -25,10 +25,10 @@ top to bottom. Run agents over a CLI, an HTTP API, or both.
|
|
|
25
25
|
- **Sessions persist automatically.** Send a message, get a reply, come
|
|
26
26
|
back later with the same session id and continue — no database to wire
|
|
27
27
|
up yourself, and it survives a crash mid-turn cleanly.
|
|
28
|
-
- **
|
|
28
|
+
- **An ability system for reusable capabilities.** Install a bundle of
|
|
29
29
|
tools, a skill, and the permission rules that gate them with one command
|
|
30
30
|
— real, reviewable files in your own repo, not an opaque dependency. See
|
|
31
|
-
[
|
|
31
|
+
[Ability system](#ability-system) below.
|
|
32
32
|
- **Does real work, safely.** Tools can hit a database, send emails, call
|
|
33
33
|
GitHub/Slack, anything with an `execute` function. Permission rules gate
|
|
34
34
|
what happens without a human: safe reads auto-run, risky actions get
|
|
@@ -118,7 +118,7 @@ redeploy needed for most of it:
|
|
|
118
118
|
| **Skills** | Create, edit, and delete `SKILL.md` files for this agent directly in the browser — write the body, preview the rendered markdown, save. |
|
|
119
119
|
| **Tools** | Local hand-written tools, gateway-sourced tools (e.g. [Composio](https://composio.dev)), and subagents-as-tools, in one place. Connect a new external gateway source or add/remove a tool without touching a file. |
|
|
120
120
|
| **ActAuth** | Add, edit, and delete permission rules — scope, tool, condition, decision — and change `default_decision`, live. |
|
|
121
|
-
| **Environment** | Every env var
|
|
121
|
+
| **Environment** | Every env var an ability (see [Ability system](#ability-system)) declared it needs, across everything installed for this agent — which ones are set, which are missing, and a form to set one. A value is never echoed back once set. |
|
|
122
122
|
|
|
123
123
|
Every tab is backed by a real API (`GET /agents/:name/config`, `.../actauth`,
|
|
124
124
|
`.../env`, ...) that reuses the exact same resolution `runAgent()` itself
|
|
@@ -170,15 +170,15 @@ click, a webhook HMAC signature, a magic-link token) ship under
|
|
|
170
170
|
live and durable, worked examples, and how resumption actually works
|
|
171
171
|
under the hood.
|
|
172
172
|
|
|
173
|
-
##
|
|
173
|
+
## Ability system
|
|
174
174
|
|
|
175
175
|
Giving an agent a new capability is usually three separate, hand-authored
|
|
176
176
|
things: a tool file, a `SKILL.md` teaching the model when to use it, and
|
|
177
|
-
an `actauth` rule allowing it to actually run. A **loopengine
|
|
177
|
+
an `actauth` rule allowing it to actually run. A **loopengine ability**
|
|
178
178
|
bundles all three into one installable unit:
|
|
179
179
|
|
|
180
180
|
```bash
|
|
181
|
-
npx loopengine add-
|
|
181
|
+
npx loopengine add-ability <spec> --agent customer-service
|
|
182
182
|
```
|
|
183
183
|
|
|
184
184
|
`<spec>` is anything `npm pack` understands — a public or private npm
|
|
@@ -189,17 +189,17 @@ dependency — reviewable, diffable, and editable the same as anything you
|
|
|
189
189
|
would have hand-written, not an opaque black box.
|
|
190
190
|
|
|
191
191
|
```bash
|
|
192
|
-
npx loopengine upgrade-
|
|
193
|
-
npx loopengine remove-
|
|
192
|
+
npx loopengine upgrade-ability <abilityName> --agent customer-service
|
|
193
|
+
npx loopengine remove-ability <abilityName> --agent customer-service
|
|
194
194
|
```
|
|
195
195
|
|
|
196
196
|
Upgrading does a real three-way merge per file — a hand-edit since install
|
|
197
197
|
survives, a genuine conflict leaves `<<<<<<<` markers to resolve by hand
|
|
198
198
|
instead of silently overwriting either side. Removing refuses a file
|
|
199
|
-
that's been modified since install unless you pass `--force`.
|
|
199
|
+
that's been modified since install unless you pass `--force`. An ability
|
|
200
200
|
can also declare the env vars its tools need, which then show up in the
|
|
201
201
|
Admin UI's [Environment tab](#admin-ui) automatically once installed. See
|
|
202
|
-
[`
|
|
202
|
+
[`ABILITIES.md`](ABILITIES.md) for the full design — format, publishing,
|
|
203
203
|
and how the merge/upgrade mechanics work in detail.
|
|
204
204
|
|
|
205
205
|
## Running an agent
|
|
@@ -1,48 +1,54 @@
|
|
|
1
|
-
export declare class
|
|
1
|
+
export declare class AbilityManifestError extends Error {
|
|
2
2
|
}
|
|
3
|
-
export declare class
|
|
3
|
+
export declare class AbilityVersionError extends Error {
|
|
4
4
|
}
|
|
5
|
-
export declare class
|
|
5
|
+
export declare class AbilityCollisionError extends Error {
|
|
6
6
|
}
|
|
7
|
-
export declare class
|
|
7
|
+
export declare class AbilityNotInstalledError extends Error {
|
|
8
8
|
}
|
|
9
|
-
export declare class
|
|
9
|
+
export declare class AbilityAlreadyInstalledError extends Error {
|
|
10
10
|
}
|
|
11
|
-
export interface
|
|
11
|
+
export interface AbilityEnvDecl {
|
|
12
12
|
name: string;
|
|
13
13
|
description?: string;
|
|
14
14
|
secret?: boolean;
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
/** `name`/`version` deliberately aren't declared here — they're read off
|
|
17
|
+
* the ability's own sibling `package.json` instead (see readManifest),
|
|
18
|
+
* which already has to exist and already has to carry real, valid values
|
|
19
|
+
* for `npm pack` to treat the directory as a fetchable package at all.
|
|
20
|
+
* loopengine.ability.json only ever needs to declare what npm has no
|
|
21
|
+
* vocabulary for. */
|
|
22
|
+
export interface AbilityManifest {
|
|
17
23
|
name: string;
|
|
18
24
|
version: string;
|
|
19
25
|
loopengineVersion: string;
|
|
20
26
|
tools?: string[];
|
|
21
27
|
skills?: string[];
|
|
22
28
|
actauth?: string;
|
|
23
|
-
env?:
|
|
29
|
+
env?: AbilityEnvDecl[];
|
|
24
30
|
}
|
|
25
|
-
/** One agent's record of one installed
|
|
31
|
+
/** One agent's record of one installed ability — the merge base a
|
|
26
32
|
* future upgrade needs, what remove needs to know is safe to delete,
|
|
27
33
|
* and (env) what the Admin UI's secrets section reads to know which
|
|
28
|
-
* vars to prompt for. Written to agents/<agent>/.loopengine-
|
|
34
|
+
* vars to prompt for. Written to agents/<agent>/.loopengine-abilities.json,
|
|
29
35
|
* same role .create-loopengine.json already plays for template files. */
|
|
30
|
-
export interface
|
|
36
|
+
export interface InstalledAbilityRecord {
|
|
31
37
|
version: string;
|
|
32
38
|
/** The exact spec (bare registry name, "name@version", a git+ssh/
|
|
33
39
|
* git+https URL with a #committish, a file: path, ...) last used to
|
|
34
|
-
* successfully install or upgrade this
|
|
35
|
-
* oldContentSpec's own doc comment for why
|
|
36
|
-
* stored verbatim rather than reconstructed from `
|
|
37
|
-
* Optional only because
|
|
40
|
+
* successfully install or upgrade this ability — see
|
|
41
|
+
* oldContentSpec's own doc comment for why upgradeAbility needs this
|
|
42
|
+
* stored verbatim rather than reconstructed from `abilityName`.
|
|
43
|
+
* Optional only because an ability installed before this field existed
|
|
38
44
|
* has no recorded value — see oldContentSpec's own fallback. */
|
|
39
45
|
spec?: string;
|
|
40
46
|
tools: string[];
|
|
41
47
|
skills: string[];
|
|
42
48
|
actauthRules: string[];
|
|
43
|
-
env:
|
|
49
|
+
env: AbilityEnvDecl[];
|
|
44
50
|
/** relative path (e.g. "tools/foo.ts") -> sha256 hex, as of the last
|
|
45
|
-
* install/upgrade — remove-
|
|
51
|
+
* install/upgrade — remove-ability's dirty-check compares against
|
|
46
52
|
* this rather than storing/refetching full content to diff. */
|
|
47
53
|
contentHashes: Record<string, string>;
|
|
48
54
|
}
|
|
@@ -52,11 +58,11 @@ export interface InstalledPackageRecord {
|
|
|
52
58
|
* accepts anything `npm pack` does: a public/private registry spec, a
|
|
53
59
|
* git URL (`github:org/repo`, `git+ssh://...`), or a local `file:../path`
|
|
54
60
|
* — the last of which is what this module's own tests point at, so no
|
|
55
|
-
* real network call is needed there; see
|
|
56
|
-
*
|
|
57
|
-
export declare function
|
|
61
|
+
* real network call is needed there; see ABILITIES.md's "Publishing an
|
|
62
|
+
* ability" section). */
|
|
63
|
+
export declare function fetchAbilityDir(spec: string): string;
|
|
58
64
|
export interface FetchOptions {
|
|
59
|
-
|
|
65
|
+
fetchAbilityDir?: (spec: string) => string;
|
|
60
66
|
/** Test-only override for the installing project's own "loopengine"
|
|
61
67
|
* dependency range — defaults to a real package.json read. Without
|
|
62
68
|
* this, checkLoopengineVersion's refusal path is unreachable from
|
|
@@ -71,7 +77,7 @@ export interface FetchOptions {
|
|
|
71
77
|
* (reusing addToolToIndex exactly as web/http-tool-admin.ts's own
|
|
72
78
|
* createHttpTool does), copies each skill directory verbatim (a raw
|
|
73
79
|
* cpSync, not skills-admin.ts's writeSkill — that regenerates
|
|
74
|
-
* frontmatter from scratch and can't carry
|
|
80
|
+
* frontmatter from scratch and can't carry an ability's own
|
|
75
81
|
* frontmatter/assets), and appends each actauth rule (addActauthRule).
|
|
76
82
|
*
|
|
77
83
|
* Deliberately does *not* attempt a live in-memory registry splice the
|
|
@@ -79,7 +85,7 @@ export interface FetchOptions {
|
|
|
79
85
|
* admin-created tool — that works there because the HTTP request
|
|
80
86
|
* creating the tool runs *inside the same process* as the already-running
|
|
81
87
|
* server, so updateAgent's mutation is visible to every later request in
|
|
82
|
-
* that same process immediately. `add-
|
|
88
|
+
* that same process immediately. `add-ability` is a separate, one-off
|
|
83
89
|
* CLI process with no connection to whatever server might be running
|
|
84
90
|
* elsewhere — even a successful getEntry/updateAgent call here would
|
|
85
91
|
* only mutate *this* CLI invocation's own throwaway registry, then
|
|
@@ -96,41 +102,41 @@ export interface FetchOptions {
|
|
|
96
102
|
*
|
|
97
103
|
* All-or-nothing: every collision check below runs, and the whole
|
|
98
104
|
* install is refused, before a single file is written. */
|
|
99
|
-
export declare function
|
|
105
|
+
export declare function installAbility(agentName: string, spec: string, options?: FetchOptions): Promise<{
|
|
100
106
|
installed: string[];
|
|
101
107
|
}>;
|
|
102
108
|
export interface UpgradeFileResult {
|
|
103
109
|
path: string;
|
|
104
110
|
status: 'updated' | 'unchanged' | 'conflict';
|
|
105
111
|
}
|
|
106
|
-
/** Upgrades an already-installed
|
|
107
|
-
* to `
|
|
112
|
+
/** Upgrades an already-installed ability to whatever `spec` (defaulting
|
|
113
|
+
* to `abilityName`, i.e. "latest") currently resolves to. Tool and skill
|
|
108
114
|
* files get a real three-way merge (mine = current file, possibly
|
|
109
115
|
* hand-edited since install; base = the version recorded at
|
|
110
116
|
* install/last-upgrade, refetched via oldContentSpec; theirs = newly
|
|
111
117
|
* fetched) — identical technique to `create-loopengine upgrade`, just
|
|
112
|
-
* applied to
|
|
118
|
+
* applied to ability-managed files instead of template files. actauth
|
|
113
119
|
* rules upgrade per-rule instead: the target actauth.yml holds rules
|
|
114
|
-
* from other
|
|
120
|
+
* from other abilities and hand-written ones too, so there's no coherent
|
|
115
121
|
* "whole file" base/theirs to merge — a rule unchanged since install
|
|
116
122
|
* updates cleanly; a hand-edited one is left alone and reported as a
|
|
117
123
|
* conflict rather than overwritten. */
|
|
118
|
-
export declare function
|
|
124
|
+
export declare function upgradeAbility(agentName: string, abilityName: string, options?: FetchOptions & {
|
|
119
125
|
spec?: string;
|
|
120
126
|
}): Promise<{
|
|
121
127
|
files: UpgradeFileResult[];
|
|
122
128
|
}>;
|
|
123
|
-
/** Removes an installed
|
|
129
|
+
/** Removes an installed ability's tool and skill files, and its actauth
|
|
124
130
|
* rules. A file whose content no longer matches the hash recorded at
|
|
125
131
|
* install/last-upgrade is refused (reported in `refused`, left on disk)
|
|
126
|
-
* unless `force` is passed — a concrete implementation of
|
|
132
|
+
* unless `force` is passed — a concrete implementation of ABILITIES.md's
|
|
127
133
|
* "refuses if any of them look hand-modified," cheaper than storing full
|
|
128
|
-
* content or refetching the
|
|
134
|
+
* content or refetching the ability to diff. Does not patch
|
|
129
135
|
* tools/index.ts to remove the now-dangling import — same "refuse
|
|
130
136
|
* rather than guess a second time" doctrine addToolToIndex's own doc
|
|
131
137
|
* comment already applies; a stale import surfaces as a clear build
|
|
132
138
|
* error, not a silent break. */
|
|
133
|
-
export declare function
|
|
139
|
+
export declare function removeAbility(agentName: string, abilityName: string, force?: boolean): {
|
|
134
140
|
removed: string[];
|
|
135
141
|
refused: string[];
|
|
136
142
|
};
|