agent-procedures 0.1.0 → 0.3.0
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 +56 -5
- package/bin/cli.js +37 -8
- package/dist/runtime.js +569 -0
- package/lib/auth.js +169 -0
- package/lib/engine.js +179 -0
- package/lib/groomer.js +129 -0
- package/lib/harnesses/claude.js +75 -0
- package/lib/harnesses/index.js +15 -0
- package/lib/init.js +60 -8
- package/lib/main.js +51 -0
- package/lib/providers.js +178 -0
- package/lib/store.js +53 -0
- package/package.json +17 -4
package/README.md
CHANGED
|
@@ -2,21 +2,72 @@
|
|
|
2
2
|
|
|
3
3
|
Procedural memory for coding agents.
|
|
4
4
|
|
|
5
|
+
Coding agents are pretty good at figuring things out. They're bad at remembering how they did it last time, so they just figure it out again. Every time.
|
|
6
|
+
|
|
7
|
+
Reflex watches the tools your agent actually runs, keeps the paths that worked, and hands them back the next time you ask for something similar. It doesn't store facts, your docs already do that. It stores how.
|
|
8
|
+
|
|
9
|
+
The npm package is `agent-procedures`. The product is Reflex.
|
|
10
|
+
|
|
11
|
+
## How it works (hot path vs cold path)
|
|
12
|
+
|
|
13
|
+
The **hot path** runs every time you prompt the agent or the agent runs a tool. It has to be fast, so it doesn't call an LLM. It's just disk I/O. When you ask for something, Reflex checks its memory for a match and injects the steps into the agent's context. When the agent uses tools, Reflex traces what happens. If the agent gets the job done without leaving broken steps behind, Reflex saves that trace as a new procedure.
|
|
14
|
+
|
|
15
|
+
The **cold path** is a background groomer. Once 5 new procedures pile up, it kicks off a background process that asks a cheap LLM to review them. It drops the risky ones and adds aliases (like synonyms) to the good ones so they match more easily next time.
|
|
16
|
+
|
|
17
|
+
You don't run either of these manually. You just use your agent.
|
|
18
|
+
|
|
19
|
+
## Status & Harnesses
|
|
20
|
+
|
|
21
|
+
Early. Reflex is built to plug into different agent platforms (harnesses). Right now, **Claude Code is the only one built** and is the default.
|
|
22
|
+
|
|
23
|
+
I set the engine up so Cursor and others can plug in later, but the adapters for those don't exist yet.
|
|
24
|
+
|
|
5
25
|
## Install
|
|
6
26
|
|
|
27
|
+
Run this in the repo you want Reflex in:
|
|
28
|
+
|
|
7
29
|
```bash
|
|
8
30
|
npx agent-procedures init
|
|
9
31
|
```
|
|
10
32
|
|
|
11
|
-
|
|
33
|
+
By default this installs the Claude Code harness. If you were using a different one later, you'd run `npx agent-procedures init --harness cursor`.
|
|
34
|
+
|
|
35
|
+
Installing the package on its own won't do anything. You need `init`. It creates the folders, copies the runtime in, and adds a hook so your agent knows to call it.
|
|
36
|
+
|
|
37
|
+
## API key (for the background groomer)
|
|
38
|
+
|
|
39
|
+
Because the groomer uses an LLM to review procedures, it needs a cheap model key.
|
|
40
|
+
|
|
41
|
+
If you already have `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` or `GEMINI_API_KEY` exported in your terminal, it just uses that. Otherwise:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx agent-procedures auth login # pick a provider, paste your key
|
|
45
|
+
npx agent-procedures auth status # check what it's using and the last groomer error
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The key gets checked before it's saved, so a typo fails right away instead of a week later in a log file. It gets stored in `~/.reflex/credentials.json` on your machine and only you can read it.
|
|
49
|
+
|
|
50
|
+
## What ends up in your repo
|
|
12
51
|
|
|
13
52
|
```
|
|
14
53
|
.reflex/
|
|
15
|
-
config.json # settings
|
|
16
|
-
procedures.jsonl # remembered
|
|
54
|
+
config.json # settings, not memory
|
|
55
|
+
procedures.jsonl # what it remembered
|
|
17
56
|
runs.jsonl # optional run outcomes
|
|
57
|
+
runtime.js # the engine, one bundled file — do not edit
|
|
58
|
+
traces/ # scratch for the current turn
|
|
18
59
|
```
|
|
19
60
|
|
|
20
|
-
|
|
61
|
+
`traces/` gets added to `.gitignore`. **Commit everything else**, including `.claude/settings.json` (the hook wiring), so anyone who clones the repo gets the same memory. If you upgrade the package, run `init` again. That overwrites `runtime.js`.
|
|
62
|
+
|
|
63
|
+
## Adding a harness
|
|
64
|
+
|
|
65
|
+
If you want to build an adapter for something other than Claude Code:
|
|
66
|
+
|
|
67
|
+
Only three things change between harnesses: where hooks get registered, what the event payload looks like, and how context gets passed back to the agent. The rest of the engine doesn't care who called it.
|
|
68
|
+
|
|
69
|
+
Adding one is a single file in `lib/harnesses/` plus one line in `lib/harnesses/index.js`. `claude.js` is the reference.
|
|
70
|
+
|
|
71
|
+
## License
|
|
21
72
|
|
|
22
|
-
|
|
73
|
+
MIT
|
package/bin/cli.js
CHANGED
|
@@ -8,19 +8,48 @@ if (!command || command === "--help" || command === "-h") {
|
|
|
8
8
|
console.log(`agent-procedures — procedural memory for coding agents (Reflex)
|
|
9
9
|
|
|
10
10
|
Usage:
|
|
11
|
-
npx agent-procedures init
|
|
11
|
+
npx agent-procedures init [--harness claude] Create .reflex/ and wire hooks
|
|
12
|
+
npx agent-procedures auth login Store an API key for the background groomer
|
|
13
|
+
npx agent-procedures auth status Show which provider/key the groomer will use
|
|
12
14
|
`);
|
|
13
15
|
process.exit(command ? 0 : 1);
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
if (command === "init") {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
const args = process.argv.slice(3);
|
|
20
|
+
const i = args.indexOf("--harness");
|
|
21
|
+
const harness = i >= 0 ? args[i + 1] : undefined;
|
|
22
|
+
try {
|
|
23
|
+
const results = init(process.cwd(), { harness });
|
|
24
|
+
console.log("Initialized Reflex in the repository");
|
|
25
|
+
console.log(` .reflex/config.json ${results.config}`);
|
|
26
|
+
console.log(` .reflex/procedures.jsonl ${results.procedures}`);
|
|
27
|
+
console.log(` .reflex/runs.jsonl ${results.runs}`);
|
|
28
|
+
console.log(` .reflex/runtime.js ${results.runtime}`);
|
|
29
|
+
console.log(` .gitignore ${results.gitignore}`);
|
|
30
|
+
console.log(` hooks (${harness || "claude"}) ${results.hooks}`);
|
|
31
|
+
process.exit(0);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error(`Error: ${e.message}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (command === "auth") {
|
|
39
|
+
const { login, status, USAGE } = await import("../lib/auth.js");
|
|
40
|
+
const [sub, ...rest] = process.argv.slice(3);
|
|
41
|
+
try {
|
|
42
|
+
if (sub === "login") await login(rest);
|
|
43
|
+
else if (sub === "status") status();
|
|
44
|
+
else {
|
|
45
|
+
console.error(USAGE);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
process.exit(0);
|
|
49
|
+
} catch (e) {
|
|
50
|
+
console.error(`Error: ${e.message}`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
24
53
|
}
|
|
25
54
|
|
|
26
55
|
console.error(`Unknown command: ${command}`);
|