leopold-driver 0.1.1 → 0.1.3
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 +19 -5
- package/assets/VERSION +1 -0
- package/assets/extensions/README.md +52 -0
- package/assets/extensions/gstack/extension.json +8 -0
- package/assets/extensions/gstack/manage.sh +68 -0
- package/assets/extensions/leopold/extension.json +8 -0
- package/assets/extensions/leopold/manage.sh +59 -0
- package/assets/extensions/ovmem/README.md +101 -0
- package/assets/extensions/ovmem/extension.json +8 -0
- package/assets/extensions/ovmem/install.sh +330 -0
- package/assets/extensions/ovmem/manage.sh +87 -0
- package/assets/extensions/ovmem/models.json +24 -0
- package/assets/extensions/ovmem/payload/RUNTIME.md +121 -0
- package/assets/extensions/ovmem/payload/ovmem-cleanup.py +148 -0
- package/assets/extensions/ovmem/payload/ovmem.py +421 -0
- package/assets/extensions/serena/README.md +50 -0
- package/assets/extensions/serena/extension.json +8 -0
- package/assets/extensions/serena/manage.sh +119 -0
- package/assets/hooks/guard-irreversible.sh +185 -0
- package/assets/hooks/hooks.json +20 -0
- package/assets/hooks/stop-continuity.sh +132 -0
- package/assets/install.sh +184 -0
- package/assets/scripts/__pycache__/leopold-watch.cpython-312.pyc +0 -0
- package/assets/scripts/leopold-doctor.sh +53 -0
- package/assets/scripts/leopold-menu.sh +132 -0
- package/assets/scripts/leopold-update-check.sh +23 -0
- package/assets/scripts/leopold-update.sh +13 -0
- package/assets/scripts/leopold-watch.py +585 -0
- package/assets/scripts/record-demo.sh +61 -0
- package/assets/scripts/test-guard.sh +76 -0
- package/assets/scripts/test-hooks.sh +121 -0
- package/assets/settings.template.json +23 -0
- package/assets/skills/leopold-brief/SKILL.md +121 -0
- package/assets/skills/leopold-doctor/SKILL.md +23 -0
- package/assets/skills/leopold-run/SKILL.md +171 -0
- package/assets/skills/leopold-status/SKILL.md +34 -0
- package/assets/skills/leopold-stop/SKILL.md +36 -0
- package/assets/skills/leopold-update/SKILL.md +27 -0
- package/assets/skills/leopold-watch/SKILL.md +48 -0
- package/assets/templates/CHARTER.md +32 -0
- package/assets/templates/DECISIONS.md +15 -0
- package/assets/templates/GUARDRAILS.md +38 -0
- package/assets/templates/MISSION.md +22 -0
- package/assets/templates/PLAN.md +9 -0
- package/dist/guard.js +82 -23
- package/dist/harness.js +71 -0
- package/dist/index.js +53 -23
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -58,14 +58,26 @@ npm run build
|
|
|
58
58
|
|
|
59
59
|
## Usage
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
This package is the whole of Leopold from npm — it bundles the harness (skills, hooks,
|
|
62
|
+
installer, extensions) so the CLI runs everything **without cloning the repo or `make`**.
|
|
63
|
+
The binary is exposed as both `leopold-driver` and `leopold`.
|
|
63
64
|
|
|
64
65
|
```bash
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
npm i -g leopold-driver
|
|
67
|
+
|
|
68
|
+
leopold install # copy skills + hooks into ~/.claude (also: --with-gstack)
|
|
69
|
+
leopold menu # toolchain manager (serena / gstack / ovmem)
|
|
70
|
+
leopold watch [--port N] # live dashboard at http://127.0.0.1:4179 (needs Python 3)
|
|
71
|
+
leopold serena install # manage an extension directly (also: gstack, ovmem)
|
|
72
|
+
leopold doctor # run every extension's doctor
|
|
73
|
+
leopold update # reinstall from this package
|
|
74
|
+
leopold run [--dry-run] # conduct the .leopold run (the SDK driver below)
|
|
67
75
|
```
|
|
68
76
|
|
|
77
|
+
`watch` reads the current project's `.leopold/` and shows run status, cost meters, the
|
|
78
|
+
event feed, decisions, and a Stop button. `run` needs a `.leopold/` brief (from
|
|
79
|
+
`/leopold-brief`) and your Claude Code login.
|
|
80
|
+
|
|
69
81
|
### Environment
|
|
70
82
|
|
|
71
83
|
| Var | Default | Purpose |
|
|
@@ -83,7 +95,9 @@ in-session engine.
|
|
|
83
95
|
## Status and known limits
|
|
84
96
|
|
|
85
97
|
Alpha. Verified: compiles against `@anthropic-ai/claude-agent-sdk`, the CLI and
|
|
86
|
-
dry-run work, the status parser
|
|
98
|
+
dry-run work, and the status parser + `canUseTool` guard have unit tests
|
|
99
|
+
(`make driver-test` / `npm test`) covering the same bypass attempts as the bash
|
|
100
|
+
guard's red-team suite. Not yet built: a
|
|
87
101
|
watchdog for a worker that ends a turn without emitting a status block (today the
|
|
88
102
|
worker is strongly instructed to always emit one), parallel multi-worker waves,
|
|
89
103
|
and the live dashboard. See the repo roadmap.
|
package/assets/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.4.4
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Leopold extension registry
|
|
2
|
+
|
|
3
|
+
The toolchain manager (`scripts/leopold-menu.sh`, or `make menu`) is data-driven: it
|
|
4
|
+
discovers everything under this directory and drives each one through a uniform contract.
|
|
5
|
+
This is the generalization of the one-off gstack prompt that used to live in `install.sh`.
|
|
6
|
+
|
|
7
|
+
## Layout
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
extensions/
|
|
11
|
+
<name>/
|
|
12
|
+
extension.json # metadata the menu renders
|
|
13
|
+
manage.sh # the actions the menu calls
|
|
14
|
+
README.md # optional, per-extension docs
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## extension.json
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"name": "gstack",
|
|
22
|
+
"title": "gstack",
|
|
23
|
+
"summary": "One-line description shown in the menu.",
|
|
24
|
+
"homepage": "https://...",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"order": 20
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`order` controls position in the menu (lower first). Convention: Leopold core 10,
|
|
31
|
+
the toolchain it conducts 20, companion capabilities 30+.
|
|
32
|
+
|
|
33
|
+
## manage.sh contract
|
|
34
|
+
|
|
35
|
+
`manage.sh <action>` where action is one of:
|
|
36
|
+
|
|
37
|
+
| action | must do | exit code |
|
|
38
|
+
|---------|---------|-----------|
|
|
39
|
+
| `detect` | nothing visible; just probe | `0` if installed, non-zero if not |
|
|
40
|
+
| `status` | print one short line (e.g. version/health) | `0` |
|
|
41
|
+
| `install` | install the component | `0` on success |
|
|
42
|
+
| `update` | update to latest | `0` on success |
|
|
43
|
+
| `remove` | uninstall (be reversible / safe where possible) | `0` on success |
|
|
44
|
+
| `doctor` | print diagnostics (what's wired, what's missing) | `0` |
|
|
45
|
+
|
|
46
|
+
Rules:
|
|
47
|
+
- Keep it idempotent. `install` run twice must not break anything.
|
|
48
|
+
- Never touch the user's git. Never print secrets.
|
|
49
|
+
- `detect` is the single source of truth for "installed?" — keep it cheap (no network).
|
|
50
|
+
- Resolve the Claude home as `${CLAUDE_HOME:-$HOME/.claude}`.
|
|
51
|
+
|
|
52
|
+
Adding a component is just dropping a new folder here with these two files.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# gstack extension - install/manage the gstack skill suite that Leopold conducts.
|
|
3
|
+
# gstack is a separate MIT project by Garry Tan: https://github.com/garrytan/gstack
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
CLAUDE="${CLAUDE_HOME:-$HOME/.claude}"
|
|
7
|
+
SKILLS="$CLAUDE/skills"
|
|
8
|
+
GSTACK_DIR="$SKILLS/gstack"
|
|
9
|
+
REPO="https://github.com/garrytan/gstack.git"
|
|
10
|
+
|
|
11
|
+
case "${1:-}" in
|
|
12
|
+
detect)
|
|
13
|
+
# installed if the clone exists, or if its skills are already present
|
|
14
|
+
[ -d "$GSTACK_DIR" ] || ls "$SKILLS" 2>/dev/null | grep -q '^spec$'
|
|
15
|
+
;;
|
|
16
|
+
|
|
17
|
+
status)
|
|
18
|
+
if [ -d "$GSTACK_DIR/.git" ]; then
|
|
19
|
+
echo "$(cd "$GSTACK_DIR" && git rev-parse --short HEAD 2>/dev/null || echo present)"
|
|
20
|
+
else
|
|
21
|
+
echo "present"
|
|
22
|
+
fi
|
|
23
|
+
;;
|
|
24
|
+
|
|
25
|
+
install)
|
|
26
|
+
if [ -d "$GSTACK_DIR" ]; then
|
|
27
|
+
echo "gstack already installed at $GSTACK_DIR"
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
command -v bun >/dev/null 2>&1 || echo "note: gstack needs Bun v1.0+ (https://bun.sh); its setup will guide you."
|
|
31
|
+
echo "-> cloning gstack into $GSTACK_DIR (shows progress; a few seconds)"
|
|
32
|
+
mkdir -p "$SKILLS"
|
|
33
|
+
git clone --progress --single-branch --depth 1 "$REPO" "$GSTACK_DIR"
|
|
34
|
+
echo "-> running gstack setup"
|
|
35
|
+
( cd "$GSTACK_DIR" && ./setup )
|
|
36
|
+
echo "gstack installed."
|
|
37
|
+
;;
|
|
38
|
+
|
|
39
|
+
update)
|
|
40
|
+
if [ ! -d "$GSTACK_DIR/.git" ]; then
|
|
41
|
+
echo "gstack not installed as a git clone; nothing to update. Run install."
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
echo "-> pulling gstack"
|
|
45
|
+
( cd "$GSTACK_DIR" && git pull --ff-only -q && ./setup )
|
|
46
|
+
echo "gstack updated."
|
|
47
|
+
;;
|
|
48
|
+
|
|
49
|
+
remove)
|
|
50
|
+
if [ -d "$GSTACK_DIR" ]; then
|
|
51
|
+
rm -rf "${GSTACK_DIR:?}"
|
|
52
|
+
echo "removed $GSTACK_DIR"
|
|
53
|
+
else
|
|
54
|
+
echo "gstack not present."
|
|
55
|
+
fi
|
|
56
|
+
;;
|
|
57
|
+
|
|
58
|
+
doctor)
|
|
59
|
+
echo "dir: $([ -d "$GSTACK_DIR" ] && echo "$GSTACK_DIR" || echo "missing")"
|
|
60
|
+
echo "bun: $(command -v bun >/dev/null 2>&1 && bun --version 2>/dev/null || echo "not found (needed for setup)")"
|
|
61
|
+
echo "spec skill: $([ -d "$SKILLS/spec" ] && echo present || echo missing)"
|
|
62
|
+
;;
|
|
63
|
+
|
|
64
|
+
*)
|
|
65
|
+
echo "usage: manage.sh {detect|status|install|update|remove|doctor}" >&2
|
|
66
|
+
exit 2
|
|
67
|
+
;;
|
|
68
|
+
esac
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Leopold core extension - manage the harness install (skills + hooks).
|
|
3
|
+
# install/update delegate to the canonical scripts so there is one source of truth.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
CLAUDE="${CLAUDE_HOME:-$HOME/.claude}"
|
|
7
|
+
LEO_HOME="$CLAUDE/leopold"
|
|
8
|
+
SKILLS="$CLAUDE/skills"
|
|
9
|
+
|
|
10
|
+
# Resolve this extension's own location to reach sibling scripts / VERSION,
|
|
11
|
+
# whether running from a clone (repo/extensions/leopold) or an install
|
|
12
|
+
# (~/.claude/leopold/extensions/leopold).
|
|
13
|
+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
14
|
+
ROOT="$(cd "$HERE/../.." && pwd)" # repo root, or ~/.claude/leopold
|
|
15
|
+
|
|
16
|
+
case "${1:-}" in
|
|
17
|
+
detect)
|
|
18
|
+
[ -d "$LEO_HOME/hooks" ] && [ -d "$SKILLS/leopold-run" ]
|
|
19
|
+
;;
|
|
20
|
+
|
|
21
|
+
status)
|
|
22
|
+
if [ -f "$ROOT/VERSION" ]; then echo "v$(cat "$ROOT/VERSION" 2>/dev/null | tr -d '[:space:]')"; else echo "installed"; fi
|
|
23
|
+
;;
|
|
24
|
+
|
|
25
|
+
install|update)
|
|
26
|
+
if [ -x "$ROOT/install.sh" ]; then
|
|
27
|
+
bash "$ROOT/install.sh"
|
|
28
|
+
elif [ -x "$LEO_HOME/scripts/leopold-update.sh" ]; then
|
|
29
|
+
bash "$LEO_HOME/scripts/leopold-update.sh"
|
|
30
|
+
else
|
|
31
|
+
echo "no installer found (expected $ROOT/install.sh or $LEO_HOME/scripts/leopold-update.sh)"
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
;;
|
|
35
|
+
|
|
36
|
+
remove)
|
|
37
|
+
echo "Removing Leopold core also removes this menu. Doing it by hand keeps you in control:"
|
|
38
|
+
echo " rm -rf $LEO_HOME"
|
|
39
|
+
echo " rm -rf $SKILLS/leopold-*"
|
|
40
|
+
echo " then remove the Stop + PreToolUse hooks from $CLAUDE/settings.json"
|
|
41
|
+
echo " (a backup was written to settings.json.leopold.bak at install time)"
|
|
42
|
+
;;
|
|
43
|
+
|
|
44
|
+
doctor)
|
|
45
|
+
if [ -x "$LEO_HOME/scripts/leopold-doctor.sh" ]; then
|
|
46
|
+
bash "$LEO_HOME/scripts/leopold-doctor.sh"
|
|
47
|
+
elif [ -x "$ROOT/scripts/leopold-doctor.sh" ]; then
|
|
48
|
+
bash "$ROOT/scripts/leopold-doctor.sh"
|
|
49
|
+
else
|
|
50
|
+
echo "skills: $([ -d "$SKILLS/leopold-run" ] && echo ok || echo missing)"
|
|
51
|
+
echo "hooks: $([ -d "$LEO_HOME/hooks" ] && echo ok || echo missing)"
|
|
52
|
+
fi
|
|
53
|
+
;;
|
|
54
|
+
|
|
55
|
+
*)
|
|
56
|
+
echo "usage: manage.sh {detect|status|install|update|remove|doctor}" >&2
|
|
57
|
+
exit 2
|
|
58
|
+
;;
|
|
59
|
+
esac
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# ovmem extension
|
|
2
|
+
|
|
3
|
+
**ovmem** gives Claude Code autonomous, self-managing long-term memory: it wires
|
|
4
|
+
[OpenViking](https://github.com/volcengine/OpenViking) (a hierarchical context DB) to
|
|
5
|
+
Claude Code through 4 native hooks, so any session stays optimized without destructive
|
|
6
|
+
`/compact` or `/clear`. Distillation, dedup and reconsolidation happen server-side; a
|
|
7
|
+
weekly hotness prune keeps the store from accumulating.
|
|
8
|
+
|
|
9
|
+
The installer is a **provider + model picker**. It runs `detect / status / install /
|
|
10
|
+
update / remove / doctor` like every extension; `install` walks you through:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
Provider: 1) openai 2) bedrock
|
|
14
|
+
chat model: gpt-4o-mini $0.15 in / $0.60 out per 1M · ctx 128k · cheap default
|
|
15
|
+
...
|
|
16
|
+
embed model: text-embedding-3-small $0.02 per 1M · 1536d · default
|
|
17
|
+
...
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Prices and the model lineup live in [`models.json`](models.json) — the single source the
|
|
21
|
+
picker reads (USD per 1M tokens, approximate, sourced from the LiteLLM price map). For
|
|
22
|
+
ovmem the real cost is **cents**: extraction only runs at PreCompact / SessionEnd.
|
|
23
|
+
|
|
24
|
+
## Providers
|
|
25
|
+
|
|
26
|
+
### OpenAI
|
|
27
|
+
|
|
28
|
+
One API key (needs the **embedding** and **`model.request`/chat** scopes). The installer
|
|
29
|
+
validates the key against both before saving it to `~/.openviking/ov.conf` (`chmod 600`).
|
|
30
|
+
|
|
31
|
+
- chat: `gpt-4o-mini` (default) · `gpt-4.1-mini` · `gpt-4o`
|
|
32
|
+
- embed: `text-embedding-3-small` (1536d, default) · `text-embedding-3-large` (3072d)
|
|
33
|
+
|
|
34
|
+
### AWS Bedrock
|
|
35
|
+
|
|
36
|
+
Routed through OpenViking's LiteLLM backends. Auth is a **Bedrock API key (bearer token)**
|
|
37
|
+
plus a **region** — that is all the user passes. The installer:
|
|
38
|
+
|
|
39
|
+
- adds `boto3` to the OpenViking tool venv (`uv tool install --with boto3 …`),
|
|
40
|
+
- writes the bearer token + region into the server's launch env (`openviking-start`, `chmod 700`),
|
|
41
|
+
- sets `vlm.provider` / `embedding.dense.provider` to `litellm` with `bedrock/…` model ids.
|
|
42
|
+
|
|
43
|
+
- chat: `nova-lite` (cheapest) · `claude-3-5-haiku` · `claude-3-5-sonnet` · `claude-sonnet-4-5`
|
|
44
|
+
- embed: `titan-embed-v2` (1024d) · `cohere-embed-v3` (1024d) · `titan-embed-v1` (1536d)
|
|
45
|
+
|
|
46
|
+
> The chat model ids use the `us.` cross-region inference profile. The model must be
|
|
47
|
+
> **enabled in your AWS account** (Bedrock → Model access). The installer's round-trip
|
|
48
|
+
> step surfaces a clear error if access/region/token is wrong. The Bedrock path is
|
|
49
|
+
> implemented against OpenViking's verified config shape but has not been run against a
|
|
50
|
+
> live AWS account in CI — treat it as beta.
|
|
51
|
+
|
|
52
|
+
## Switching providers / reconfiguring
|
|
53
|
+
|
|
54
|
+
Run `install` (or `update`) from the toolchain menu again — it is also the reconfigure
|
|
55
|
+
path. It detects the current setup, **offers to reuse the existing credential**, defaults
|
|
56
|
+
every prompt to your current choice, and:
|
|
57
|
+
|
|
58
|
+
- **Chat-only change** (or new model, same embedding) → just rewrites `ov.conf` and
|
|
59
|
+
restarts. Your memories are untouched.
|
|
60
|
+
- **Embedding change** (e.g. OpenAI → Bedrock, where the dimension goes 1536 → 1024) →
|
|
61
|
+
the vector index is **rebuilt**: it backs up and drops the index, lets the server
|
|
62
|
+
recreate it at the new dimension, then re-embeds every memory (`content/reindex`). Your
|
|
63
|
+
memory **content is preserved** — only the index is rebuilt. If the rebuild fails, the
|
|
64
|
+
previous index **and** config are restored automatically.
|
|
65
|
+
|
|
66
|
+
Server restarts are lock-aware (one OpenViking process per data dir — a kill+restart race
|
|
67
|
+
on the data-dir lock is exactly what breaks otherwise).
|
|
68
|
+
|
|
69
|
+
## Notes that bite
|
|
70
|
+
|
|
71
|
+
- **The embedding model sets the vector dimension** (1536 / 3072 / 1024), baked into the
|
|
72
|
+
vectordb. Changing it is handled by the reindex above, but it re-embeds the whole store
|
|
73
|
+
(cents + a few seconds), so don't flip it casually.
|
|
74
|
+
- **`vlm.max_tokens`**: 16384 for OpenAI gpt-4o-mini (its cap), 8192 for Bedrock.
|
|
75
|
+
- **`output_language_override: "en"`** pins memory + summaries to English.
|
|
76
|
+
|
|
77
|
+
## Headless / CI install
|
|
78
|
+
|
|
79
|
+
No terminal? Set the choices via env (the picker reads `/dev/tty` interactively, or these
|
|
80
|
+
when there is none):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
OVMEM_PROVIDER=openai OVMEM_CHAT_MODEL=gpt-4o-mini OVMEM_EMBED_MODEL=text-embedding-3-small \
|
|
84
|
+
OPENAI_API_KEY=sk-... bash install.sh
|
|
85
|
+
# or
|
|
86
|
+
OVMEM_PROVIDER=bedrock OVMEM_CHAT_MODEL=claude-3-5-haiku OVMEM_EMBED_MODEL=titan-embed-v2 \
|
|
87
|
+
AWS_BEARER_TOKEN_BEDROCK=... AWS_REGION=us-east-1 bash install.sh
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Runtime model (reference)
|
|
91
|
+
|
|
92
|
+
4 hooks → OpenViking REST:
|
|
93
|
+
- **SessionStart** — bootstrap the server + rehydrate (session summary + long-term memory)
|
|
94
|
+
- **UserPromptSubmit** — recall: inject memory relevant to the prompt (token-budgeted)
|
|
95
|
+
- **PreCompact** — flush the transcript delta + commit *before* compaction destroys it
|
|
96
|
+
- **SessionEnd** — flush + commit, then the weekly hotness prune (`ovmem-cleanup.py`)
|
|
97
|
+
|
|
98
|
+
Dedup and obsolescence are handled natively by OpenViking on commit. Cold-memory
|
|
99
|
+
accumulation is pruned by `ovmem-cleanup.py` (hotness = frequency × recency decay).
|
|
100
|
+
Everything is local: the server binds `127.0.0.1` only. The lone outbound call is to the
|
|
101
|
+
chosen provider (OpenAI or Bedrock, with the user's own credential) for embeddings/extraction.
|