hippo-memory 0.2.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/LICENSE +21 -0
- package/README.md +305 -0
- package/dist/autolearn.d.ts +34 -0
- package/dist/autolearn.d.ts.map +1 -0
- package/dist/autolearn.js +119 -0
- package/dist/autolearn.js.map +1 -0
- package/dist/cli.d.ts +21 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +956 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/consolidate.d.ts +24 -0
- package/dist/consolidate.d.ts.map +1 -0
- package/dist/consolidate.js +133 -0
- package/dist/consolidate.js.map +1 -0
- package/dist/embeddings.d.ts +39 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +184 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/memory.d.ts +59 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +118 -0
- package/dist/memory.js.map +1 -0
- package/dist/search.d.ts +51 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +239 -0
- package/dist/search.js.map +1 -0
- package/dist/shared.d.ts +38 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +111 -0
- package/dist/shared.js.map +1 -0
- package/dist/store.d.ts +70 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +244 -0
- package/dist/store.js.map +1 -0
- package/dist/yaml.d.ts +14 -0
- package/dist/yaml.d.ts.map +1 -0
- package/dist/yaml.js +81 -0
- package/dist/yaml.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Keith So
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# 🦛 Hippo
|
|
2
|
+
|
|
3
|
+
**Every AI memory tool remembers everything. The brain doesn't. That's why it works.**
|
|
4
|
+
|
|
5
|
+
[](https://npmjs.com/package/hippo-memory)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## The Problem
|
|
11
|
+
|
|
12
|
+
AI agents forget everything between sessions. Existing solutions just save everything and search later. That's a filing cabinet, not a brain.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g hippo-memory
|
|
20
|
+
|
|
21
|
+
hippo init
|
|
22
|
+
hippo remember "FRED cache silently dropped the tips_10y series" --tag error
|
|
23
|
+
hippo recall "data pipeline issues" --budget 2000
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That's it. You have a memory system.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## How It Works
|
|
31
|
+
|
|
32
|
+
Input enters the buffer. Important things get encoded into episodic memory. During "sleep," repeated episodes compress into semantic patterns. Weak memories decay and disappear.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
New information
|
|
36
|
+
│
|
|
37
|
+
▼
|
|
38
|
+
┌─────────────┐
|
|
39
|
+
│ Buffer │ Working memory. Current session only. No decay.
|
|
40
|
+
│ (session) │
|
|
41
|
+
└──────┬──────┘
|
|
42
|
+
│ encoded (tags, strength, half-life assigned)
|
|
43
|
+
▼
|
|
44
|
+
┌─────────────┐
|
|
45
|
+
│ Episodic │ Timestamped memories. Decay by default.
|
|
46
|
+
│ Store │ Retrieval strengthens. Errors stick longer.
|
|
47
|
+
└──────┬──────┘
|
|
48
|
+
│ consolidation (hippo sleep)
|
|
49
|
+
▼
|
|
50
|
+
┌─────────────┐
|
|
51
|
+
│ Semantic │ Compressed patterns. Stable. Schema-aware.
|
|
52
|
+
│ Store │ Extracted from repeated episodes.
|
|
53
|
+
└─────────────┘
|
|
54
|
+
|
|
55
|
+
💤 hippo sleep: decay + replay + merge
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Key Features
|
|
61
|
+
|
|
62
|
+
### Decay by default
|
|
63
|
+
|
|
64
|
+
Every memory has a half-life. 7 days by default. Persistence is earned.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
hippo remember "always check cache contents after refresh"
|
|
68
|
+
# stored with half_life: 7d, strength: 1.0
|
|
69
|
+
|
|
70
|
+
# 14 days later with no retrieval:
|
|
71
|
+
hippo inspect mem_a1b2c3
|
|
72
|
+
# strength: 0.25 (decayed by 2 half-lives)
|
|
73
|
+
# at risk of removal on next sleep
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### Retrieval strengthens
|
|
79
|
+
|
|
80
|
+
Use it or lose it. Each recall boosts the half-life by 2 days.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
hippo recall "cache issues"
|
|
84
|
+
# finds mem_a1b2c3, retrieval_count: 1 → 2
|
|
85
|
+
# half_life extended: 7d → 9d
|
|
86
|
+
# strength recalculated from retrieval timestamp
|
|
87
|
+
|
|
88
|
+
hippo recall "cache issues" # again next week
|
|
89
|
+
# retrieval_count: 2 → 3
|
|
90
|
+
# half_life: 9d → 11d
|
|
91
|
+
# this memory is learning to survive
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### Error memories stick
|
|
97
|
+
|
|
98
|
+
Tag a memory as an error and it gets 2x the half-life automatically.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
hippo remember "deployment failed: forgot to run migrations" --error
|
|
102
|
+
# half_life: 14d instead of 7d
|
|
103
|
+
# emotional_valence: negative
|
|
104
|
+
# strength formula applies 1.5x multiplier
|
|
105
|
+
|
|
106
|
+
# production incidents don't fade quietly
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### Sleep consolidation
|
|
112
|
+
|
|
113
|
+
Run `hippo sleep` and episodes compress into patterns.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
hippo sleep
|
|
117
|
+
|
|
118
|
+
# 💤 Running consolidation...
|
|
119
|
+
#
|
|
120
|
+
# 📊 Results:
|
|
121
|
+
# Active memories: 23
|
|
122
|
+
# Removed (decayed): 4
|
|
123
|
+
# Merged episodic: 6
|
|
124
|
+
# New semantic: 2
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Three or more related episodes get merged into a single semantic memory. The originals decay. The pattern survives.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### Outcome feedback
|
|
132
|
+
|
|
133
|
+
Did the recalled memories actually help? Tell Hippo. It tightens the feedback loop.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
hippo recall "why is the gold model broken"
|
|
137
|
+
# ... you read the memories and fix the bug ...
|
|
138
|
+
|
|
139
|
+
hippo outcome --good
|
|
140
|
+
# 👍 Applied positive outcome to 3 memories
|
|
141
|
+
# half_life +5d on each
|
|
142
|
+
|
|
143
|
+
hippo outcome --bad
|
|
144
|
+
# 👎 Applied negative outcome to 3 memories
|
|
145
|
+
# half_life -3d on each
|
|
146
|
+
# irrelevant memories decay faster
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### Token budgets
|
|
152
|
+
|
|
153
|
+
Recall only what fits. No context stuffing.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# fits within Claude's 2K token window for task context
|
|
157
|
+
hippo recall "deployment checklist" --budget 2000
|
|
158
|
+
|
|
159
|
+
# need more for a big task
|
|
160
|
+
hippo recall "full project history" --budget 8000
|
|
161
|
+
|
|
162
|
+
# machine-readable for programmatic use
|
|
163
|
+
hippo recall "api errors" --budget 1000 --json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Results are ranked by `relevance * strength * recency`. The highest-signal memories fill the budget first.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## CLI Reference
|
|
171
|
+
|
|
172
|
+
| Command | What it does |
|
|
173
|
+
|---------|-------------|
|
|
174
|
+
| `hippo init` | Create `.hippo/` in current directory |
|
|
175
|
+
| `hippo remember "<text>"` | Store a memory |
|
|
176
|
+
| `hippo remember "<text>" --tag <t>` | Store with tag (repeatable) |
|
|
177
|
+
| `hippo remember "<text>" --error` | Store as error (2x half-life) |
|
|
178
|
+
| `hippo remember "<text>" --pin` | Store with no decay |
|
|
179
|
+
| `hippo recall "<query>"` | Retrieve relevant memories |
|
|
180
|
+
| `hippo recall "<query>" --budget <n>` | Recall within token limit (default: 4000) |
|
|
181
|
+
| `hippo recall "<query>" --json` | Output as JSON |
|
|
182
|
+
| `hippo context --auto` | Smart context injection (auto-detects task from git) |
|
|
183
|
+
| `hippo context "<query>" --budget <n>` | Context injection with explicit query (default: 1500) |
|
|
184
|
+
| `hippo context --budget 0` | Skip entirely (zero token cost) |
|
|
185
|
+
| `hippo hook list` | Show available framework hooks |
|
|
186
|
+
| `hippo hook install <target>` | Install hook (claude-code, codex, cursor, openclaw) |
|
|
187
|
+
| `hippo hook uninstall <target>` | Remove hook |
|
|
188
|
+
| `hippo sleep` | Run consolidation (decay + merge + compress) |
|
|
189
|
+
| `hippo sleep --dry-run` | Preview consolidation without writing |
|
|
190
|
+
| `hippo status` | Memory health: counts, strengths, last sleep |
|
|
191
|
+
| `hippo outcome --good` | Strengthen last recalled memories |
|
|
192
|
+
| `hippo outcome --bad` | Weaken last recalled memories |
|
|
193
|
+
| `hippo outcome --id <id> --good` | Target a specific memory |
|
|
194
|
+
| `hippo inspect <id>` | Full detail on one memory |
|
|
195
|
+
| `hippo forget <id>` | Force remove a memory |
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Framework Integrations
|
|
200
|
+
|
|
201
|
+
One command. Done.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
hippo hook install claude-code # patches CLAUDE.md
|
|
205
|
+
hippo hook install codex # patches AGENTS.md
|
|
206
|
+
hippo hook install cursor # patches .cursorrules
|
|
207
|
+
hippo hook install openclaw # creates .openclaw/skills/hippo/SKILL.md
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
This adds a `<!-- hippo:start -->` ... `<!-- hippo:end -->` block that tells the agent to:
|
|
211
|
+
1. Run `hippo context --auto --budget 1500` at session start
|
|
212
|
+
2. Run `hippo remember "<lesson>" --error` on errors
|
|
213
|
+
3. Run `hippo outcome --good` on completion
|
|
214
|
+
|
|
215
|
+
To remove: `hippo hook uninstall claude-code`
|
|
216
|
+
|
|
217
|
+
### What the hook adds (Claude Code example)
|
|
218
|
+
|
|
219
|
+
```markdown
|
|
220
|
+
## Project Memory (Hippo)
|
|
221
|
+
|
|
222
|
+
Before starting work, load relevant context:
|
|
223
|
+
hippo context --auto --budget 1500
|
|
224
|
+
|
|
225
|
+
When you hit an error or discover a gotcha:
|
|
226
|
+
hippo remember "<what went wrong and why>" --error
|
|
227
|
+
|
|
228
|
+
After completing work successfully:
|
|
229
|
+
hippo outcome --good
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Generic / MCP
|
|
233
|
+
|
|
234
|
+
For any agent that can run shell commands:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"tools": [
|
|
239
|
+
{
|
|
240
|
+
"name": "memory_context",
|
|
241
|
+
"description": "Load relevant project memory for the current task",
|
|
242
|
+
"command": "hippo context --auto --budget 1500"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"name": "memory_store",
|
|
246
|
+
"description": "Store a new memory",
|
|
247
|
+
"command": "hippo remember {text} --error"
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Full integration details: [integrations/](integrations/)
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## The Neuroscience
|
|
258
|
+
|
|
259
|
+
Hippo is modeled on seven properties of the human hippocampus. Not metaphorically. Literally.
|
|
260
|
+
|
|
261
|
+
**Why two stores?** The brain uses a fast hippocampal buffer + a slow neocortical store (Complementary Learning Systems theory, McClelland et al. 1995). If the neocortex learned fast, new information would overwrite old knowledge. The buffer absorbs new episodes; the neocortex extracts patterns over time.
|
|
262
|
+
|
|
263
|
+
**Why does decay help?** New neurons born in the dentate gyrus actively disrupt old memory traces (Frankland et al. 2013). This is adaptive: it reduces interference from outdated information. Forgetting isn't failure. It's maintenance.
|
|
264
|
+
|
|
265
|
+
**Why do errors stick?** The amygdala modulates hippocampal consolidation based on emotional significance. Fear and error signals boost encoding. Your first production incident is burned into memory. Your 200th uneventful deploy isn't.
|
|
266
|
+
|
|
267
|
+
**Why does retrieval strengthen?** Recalled memories undergo "reconsolidation" (Nader et al. 2000). The act of retrieval destabilizes the trace, then re-encodes it stronger. This is the testing effect. Hippo implements it mechanically via the half-life extension on recall.
|
|
268
|
+
|
|
269
|
+
**Why does sleep consolidate?** During sleep, the hippocampus replays compressed versions of recent episodes and "teaches" the neocortex by repeatedly activating the same patterns. Hippo's `sleep` command runs this as a deliberate consolidation pass.
|
|
270
|
+
|
|
271
|
+
The 7 mechanisms in full: [PLAN.md#core-principles](PLAN.md#core-principles)
|
|
272
|
+
|
|
273
|
+
For how these mechanisms connect to LLM training, continual learning, and open research problems: **[RESEARCH.md](RESEARCH.md)**
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Comparison
|
|
278
|
+
|
|
279
|
+
| Feature | Hippo | Mem0 | Basic Memory | Claude-Mem |
|
|
280
|
+
|---------|-------|------|-------------|-----------|
|
|
281
|
+
| Decay by default | ✅ | ❌ | ❌ | ❌ |
|
|
282
|
+
| Retrieval strengthening | ✅ | ❌ | ❌ | ❌ |
|
|
283
|
+
| Outcome tracking | ✅ | ❌ | ❌ | ❌ |
|
|
284
|
+
| Zero dependencies | ✅ | ❌ | ❌ | ❌ |
|
|
285
|
+
| Git-friendly | ✅ | ❌ | ✅ | ❌ |
|
|
286
|
+
| Framework agnostic | ✅ | Partial | ✅ | ❌ |
|
|
287
|
+
|
|
288
|
+
Mem0, Basic Memory, and Claude-Mem all implement "save everything, search later." Hippo is the only one that models what memories are worth keeping.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Contributing
|
|
293
|
+
|
|
294
|
+
Issues and PRs welcome. Before contributing, run `hippo status` in the repo root to see the project's own memory.
|
|
295
|
+
|
|
296
|
+
The interesting problems:
|
|
297
|
+
- Better consolidation heuristics (what makes a good semantic memory?)
|
|
298
|
+
- Embedding-based search (currently BM25 only)
|
|
299
|
+
- MCP server wrapper
|
|
300
|
+
- Conflict detection between semantic memories
|
|
301
|
+
- Schema acceleration (fast-track memories that fit existing patterns)
|
|
302
|
+
|
|
303
|
+
## License
|
|
304
|
+
|
|
305
|
+
MIT
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-learn from errors and git history.
|
|
3
|
+
* Agents learn from failures without explicit hippo remember calls.
|
|
4
|
+
*/
|
|
5
|
+
import { MemoryEntry } from './memory.js';
|
|
6
|
+
/**
|
|
7
|
+
* Create a MemoryEntry capturing a command failure.
|
|
8
|
+
* Content format: "Command '<cmd>' failed: <truncated stderr>"
|
|
9
|
+
*/
|
|
10
|
+
export declare function captureError(exitCode: number, stderr: string, command: string): MemoryEntry;
|
|
11
|
+
/**
|
|
12
|
+
* Parse git log output for actionable lessons.
|
|
13
|
+
* Looks for fix:, revert:, bug:, error:, hotfix: commit messages.
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractLessons(gitLog: string): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Check if a substantially similar memory already exists.
|
|
18
|
+
* Returns true if overlap > threshold (default 0.7).
|
|
19
|
+
*/
|
|
20
|
+
export declare function deduplicateLesson(hippoRoot: string, lesson: string, threshold?: number): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Run a command, streaming stdout/stderr to the terminal in real time.
|
|
23
|
+
* Returns: { exitCode, stderr }.
|
|
24
|
+
*/
|
|
25
|
+
export declare function runWatched(command: string): Promise<{
|
|
26
|
+
exitCode: number;
|
|
27
|
+
stderr: string;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Fetch recent git log lines (subject lines only).
|
|
31
|
+
* days: how many days of history to include.
|
|
32
|
+
*/
|
|
33
|
+
export declare function fetchGitLog(cwd: string, days: number): string;
|
|
34
|
+
//# sourceMappingURL=autolearn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autolearn.d.ts","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAI/D;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,WAAW,CAiBb;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAqCvD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,SAAM,GACd,OAAO,CAST;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBzF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW7D"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-learn from errors and git history.
|
|
3
|
+
* Agents learn from failures without explicit hippo remember calls.
|
|
4
|
+
*/
|
|
5
|
+
import { execSync, spawn } from 'child_process';
|
|
6
|
+
import { createMemory, Layer } from './memory.js';
|
|
7
|
+
import { loadAllEntries } from './store.js';
|
|
8
|
+
import { textOverlap } from './search.js';
|
|
9
|
+
/**
|
|
10
|
+
* Create a MemoryEntry capturing a command failure.
|
|
11
|
+
* Content format: "Command '<cmd>' failed: <truncated stderr>"
|
|
12
|
+
*/
|
|
13
|
+
export function captureError(exitCode, stderr, command) {
|
|
14
|
+
// Truncate to first 500 chars to avoid storing megabytes of build logs
|
|
15
|
+
const wasTruncated = stderr.length > 500;
|
|
16
|
+
const truncated = stderr.slice(0, 500).trim();
|
|
17
|
+
const suffix = wasTruncated ? ' [truncated]' : '';
|
|
18
|
+
const content = `Command '${command}' failed (exit ${exitCode}): ${truncated}${suffix}`;
|
|
19
|
+
// Derive a sanitized tag from the command name (first word, strip path)
|
|
20
|
+
const cmdBase = command.trim().split(/\s+/)[0].replace(/[^a-zA-Z0-9-]/g, '');
|
|
21
|
+
const tags = ['error', 'autolearn'];
|
|
22
|
+
if (cmdBase)
|
|
23
|
+
tags.push(cmdBase.toLowerCase().slice(0, 30));
|
|
24
|
+
return createMemory(content, {
|
|
25
|
+
layer: Layer.Episodic,
|
|
26
|
+
tags,
|
|
27
|
+
source: 'autolearn',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Parse git log output for actionable lessons.
|
|
32
|
+
* Looks for fix:, revert:, bug:, error:, hotfix: commit messages.
|
|
33
|
+
*/
|
|
34
|
+
export function extractLessons(gitLog) {
|
|
35
|
+
const lessons = [];
|
|
36
|
+
const lines = gitLog.split('\n');
|
|
37
|
+
// Patterns that indicate a lesson to learn from
|
|
38
|
+
// Handle git log formats: "abc1234 fix: message" or "Fix broken thing"
|
|
39
|
+
const patterns = [
|
|
40
|
+
/^[a-f0-9]+\s+(fix|revert|bug|error|hotfix|bugfix)(\(.+?\))?:?\s+(.+)/i,
|
|
41
|
+
/^(fix|revert|bug|error|hotfix|bugfix)(\(.+?\))?:?\s+(.+)/i,
|
|
42
|
+
/^(Fix|Revert|Bug|Hotfix|Bugfix)\s+(.+)/,
|
|
43
|
+
/\b(fixed|reverted|corrected|resolved)\b.{3,100}/i,
|
|
44
|
+
];
|
|
45
|
+
for (const line of lines) {
|
|
46
|
+
const trimmed = line.trim();
|
|
47
|
+
if (!trimmed || trimmed.startsWith('commit ') || trimmed.startsWith('Author:') || trimmed.startsWith('Date:')) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
// Strip leading git hash if present (real hashes are hex, but be lenient with alphanumeric prefixes)
|
|
51
|
+
const subject = trimmed.replace(/^[a-z0-9]{6,40}\s+/i, '');
|
|
52
|
+
for (const pat of patterns) {
|
|
53
|
+
const m = subject.match(pat);
|
|
54
|
+
if (m) {
|
|
55
|
+
// For conventional commits: use group 3 (message after prefix), group 2, or full match
|
|
56
|
+
const lesson = (m[3] ?? m[2] ?? m[0]).trim();
|
|
57
|
+
if (lesson.length > 5 && lesson.length < 500) {
|
|
58
|
+
lessons.push(lesson);
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Deduplicate exact matches at extraction time
|
|
65
|
+
return [...new Set(lessons)];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check if a substantially similar memory already exists.
|
|
69
|
+
* Returns true if overlap > threshold (default 0.7).
|
|
70
|
+
*/
|
|
71
|
+
export function deduplicateLesson(hippoRoot, lesson, threshold = 0.7) {
|
|
72
|
+
const entries = loadAllEntries(hippoRoot);
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
const overlap = textOverlap(lesson, entry.content);
|
|
75
|
+
if (overlap > threshold)
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Run a command, streaming stdout/stderr to the terminal in real time.
|
|
82
|
+
* Returns: { exitCode, stderr }.
|
|
83
|
+
*/
|
|
84
|
+
export function runWatched(command) {
|
|
85
|
+
return new Promise((resolve) => {
|
|
86
|
+
// Use shell: true so the command string is handled by the shell as-is
|
|
87
|
+
const child = spawn(command, { shell: true, stdio: ['inherit', 'inherit', 'pipe'] });
|
|
88
|
+
const stderrChunks = [];
|
|
89
|
+
child.stderr.on('data', (chunk) => {
|
|
90
|
+
stderrChunks.push(chunk);
|
|
91
|
+
// Also pass through to terminal
|
|
92
|
+
process.stderr.write(chunk);
|
|
93
|
+
});
|
|
94
|
+
child.on('close', (code) => {
|
|
95
|
+
resolve({
|
|
96
|
+
exitCode: code ?? 1,
|
|
97
|
+
stderr: Buffer.concat(stderrChunks).toString('utf8'),
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
child.on('error', (err) => {
|
|
101
|
+
resolve({ exitCode: 1, stderr: err.message });
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Fetch recent git log lines (subject lines only).
|
|
107
|
+
* days: how many days of history to include.
|
|
108
|
+
*/
|
|
109
|
+
export function fetchGitLog(cwd, days) {
|
|
110
|
+
try {
|
|
111
|
+
const since = `--since="${days} days ago"`;
|
|
112
|
+
const raw = execSync(`git log ${since} --pretty=format:"%s" 2>&1`, { encoding: 'utf8', cwd, timeout: 10000 });
|
|
113
|
+
return raw;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return '';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=autolearn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autolearn.js","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Hippo CLI - biologically-inspired memory system for AI agents.
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* hippo init [--global]
|
|
7
|
+
* hippo remember <text> [--tag <t>] [--error] [--pin] [--global]
|
|
8
|
+
* hippo recall <query> [--budget <n>] [--json]
|
|
9
|
+
* hippo sleep [--dry-run]
|
|
10
|
+
* hippo status
|
|
11
|
+
* hippo outcome --good | --bad [--id <id>]
|
|
12
|
+
* hippo forget <id>
|
|
13
|
+
* hippo inspect <id>
|
|
14
|
+
* hippo embed [--status]
|
|
15
|
+
* hippo watch "<command>"
|
|
16
|
+
* hippo learn --git [--days <n>]
|
|
17
|
+
* hippo promote <id>
|
|
18
|
+
* hippo sync
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
|