@vib795/agent-memory 0.3.0 → 0.4.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 +27 -17
- package/package.json +1 -9
- package/src/cli.js +14 -9
- package/src/config.js +61 -29
- package/src/setup.js +4 -4
- package/install.ps1 +0 -71
- package/install.sh +0 -36
- package/scripts/postinstall.js +0 -45
- package/uninstall.ps1 +0 -54
- package/uninstall.sh +0 -39
- package/update.ps1 +0 -45
- package/update.sh +0 -26
package/README.md
CHANGED
|
@@ -162,6 +162,17 @@ exactly what would go.
|
|
|
162
162
|
Everything already captured stays in `default`, at the same path as before. Nothing
|
|
163
163
|
migrates and nothing changes until you create a second engagement.
|
|
164
164
|
|
|
165
|
+
**Two things sit outside the boundary, deliberately.** Skill installation is shared,
|
|
166
|
+
because every engagement reads the same three skill files and registering them per
|
|
167
|
+
engagement would leave the description stale after a switch. Handoff files are shared
|
|
168
|
+
too — they live in `~/.agents/handoffs`, not in a store — so `purge` does not remove
|
|
169
|
+
them and says so every time rather than letting "the store is gone" be mistaken for
|
|
170
|
+
"their context is gone".
|
|
171
|
+
|
|
172
|
+
Most people need none of this. If each client already gives you a separate machine,
|
|
173
|
+
that boundary is stronger than anything here, and the default engagement is all you
|
|
174
|
+
will ever touch.
|
|
175
|
+
|
|
165
176
|
## CLI
|
|
166
177
|
|
|
167
178
|
```
|
|
@@ -268,10 +279,11 @@ npm install -g ./agent-memory
|
|
|
268
279
|
agent-memory setup
|
|
269
280
|
```
|
|
270
281
|
|
|
271
|
-
**Do not install from the git URL directly.** `npm install -g <git-url>`
|
|
272
|
-
this package: npm
|
|
273
|
-
|
|
274
|
-
|
|
282
|
+
**Do not install from the git URL directly.** `npm install -g <git-url>` does not
|
|
283
|
+
work for this package: npm resolves a git install through
|
|
284
|
+
`~/.npm/_cacache/tmp/git-clone*` and then removes that directory, leaving the global
|
|
285
|
+
install pointing at a path that no longer exists. Cloning first avoids npm's git
|
|
286
|
+
handling entirely. Verified on npm 11.18.
|
|
275
287
|
|
|
276
288
|
Every release is mirrored to **GitHub Packages**. Treat that as redundancy rather
|
|
277
289
|
than a second front door: GitHub Packages requires authentication even for public
|
|
@@ -313,17 +325,16 @@ drift, and `compact` regenerates the routing digest into both.
|
|
|
313
325
|
`agent-memory doctor` lists what it detected, so an install that appears to do
|
|
314
326
|
nothing tells you whether your editor was missed or simply ignored the files.
|
|
315
327
|
|
|
316
|
-
**Why it is not automatic.**
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
```
|
|
328
|
+
**Why it is not automatic.** Installing the package writes nothing to your machine.
|
|
329
|
+
There is no `postinstall` hook, and its absence is a security decision rather than an
|
|
330
|
+
omission: an install script that writes into *other* tools' agent directories —
|
|
331
|
+
`~/.claude`, `~/.codex`, your editor's prompt folder — is mechanically
|
|
332
|
+
indistinguishable from a supply-chain attack that hijacks an AI agent, and
|
|
333
|
+
supply-chain scanners classify it as exactly that. Installing this package and
|
|
334
|
+
granting it your agents are two separate decisions, so they are two commands.
|
|
335
|
+
`agent-memory setup` is the one that asks.
|
|
325
336
|
|
|
326
|
-
|
|
337
|
+
`agent-memory doctor` tells you where you stand. It checks the files
|
|
327
338
|
rather than the tools, and names any agent it found that has no skills in it:
|
|
328
339
|
|
|
329
340
|
```
|
|
@@ -376,10 +387,9 @@ Note that `npm install -g .` from a clone *symlinks* rather than copies, so
|
|
|
376
387
|
`skills/recall/SKILL.md` will show as modified. That is expected — the description
|
|
377
388
|
is generated state, and the committed value is only a placeholder.
|
|
378
389
|
|
|
379
|
-
Needs Node 22.5 or newer; `doctor` says so plainly if the version is too old
|
|
380
|
-
`postinstall` refuses rather than failing your install.
|
|
390
|
+
Needs Node 22.5 or newer; `doctor` says so plainly if the version is too old.
|
|
381
391
|
|
|
382
|
-
Run `npm test` for the suite (
|
|
392
|
+
Run `npm test` for the suite (78 tests, no dependencies). CI runs it on Linux,
|
|
383
393
|
macOS and Windows across Node 22 and 24, and separately installs the packed tarball
|
|
384
394
|
and exercises it end to end on all three.
|
|
385
395
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vib795/agent-memory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Durable cross-repo knowledge graph for GitHub Copilot and Claude Code. Markdown source of truth, disposable SQLite index, zero runtime dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github-copilot",
|
|
@@ -27,19 +27,11 @@
|
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"test": "node --test",
|
|
30
|
-
"postinstall": "node scripts/postinstall.js",
|
|
31
30
|
"setup": "node src/cli.js setup"
|
|
32
31
|
},
|
|
33
32
|
"files": [
|
|
34
33
|
"src/",
|
|
35
|
-
"scripts/",
|
|
36
34
|
"skills/",
|
|
37
|
-
"install.sh",
|
|
38
|
-
"install.ps1",
|
|
39
|
-
"update.sh",
|
|
40
|
-
"update.ps1",
|
|
41
|
-
"uninstall.sh",
|
|
42
|
-
"uninstall.ps1",
|
|
43
35
|
"README.md",
|
|
44
36
|
"HOWTO.md",
|
|
45
37
|
"LICENSE"
|
package/src/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ import { compact, maybeCompact } from './compact.js';
|
|
|
15
15
|
import { staleness, currentRepo, reviewCandidates, captureGap } from './staleness.js';
|
|
16
16
|
import { setup as runSetup, unlinkSkills, danglingSkillLinks, SKILLS } from './setup.js';
|
|
17
17
|
import { detectTargets, installableTargets } from './targets.js';
|
|
18
|
-
import { join } from 'node:path';
|
|
18
|
+
import { join, dirname } from 'node:path';
|
|
19
19
|
import { atomicWrite } from './atomic.js';
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -131,10 +131,10 @@ function cmdInit(opts) {
|
|
|
131
131
|
/**
|
|
132
132
|
* Link the skills into both agents and build the store.
|
|
133
133
|
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
134
|
+
* This is the only thing that writes into an agent's directory, and it only runs when
|
|
135
|
+
* a person types it. The package deliberately ships no install hook: writing into
|
|
136
|
+
* another tool's agent surface from an install script is the shape of a supply-chain
|
|
137
|
+
* agent hijack, whoever does it and for whatever reason.
|
|
138
138
|
*/
|
|
139
139
|
function cmdSetup() {
|
|
140
140
|
ensureStore();
|
|
@@ -496,10 +496,10 @@ function cmdDoctor() {
|
|
|
496
496
|
);
|
|
497
497
|
|
|
498
498
|
// Detection is not installation, and conflating them is how this tool reports
|
|
499
|
-
// healthy while doing nothing.
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
-
//
|
|
499
|
+
// healthy while doing nothing. Installing the package does not install the skills;
|
|
500
|
+
// only `agent-memory setup` does, so the CLI routinely lands on PATH with every
|
|
501
|
+
// agent directory empty while every other check here still passes. Verify the
|
|
502
|
+
// files, per agent, rather than trusting that setup ever ran.
|
|
503
503
|
const gaps = [];
|
|
504
504
|
for (const t of installableTargets()) {
|
|
505
505
|
const absent = SKILLS.filter((name) =>
|
|
@@ -807,6 +807,11 @@ function cmdEngagement(opts) {
|
|
|
807
807
|
text: [
|
|
808
808
|
`Purged engagement ${name}: ${notes} note${notes === 1 ? '' : 's'} removed.`,
|
|
809
809
|
`${dir} no longer exists.`,
|
|
810
|
+
'',
|
|
811
|
+
// Said every time, because the gap between "the store is gone" and "their
|
|
812
|
+
// knowledge is gone" is exactly the assumption someone would make here.
|
|
813
|
+
'Handoff files are not part of an engagement store and were not touched.',
|
|
814
|
+
`Review ${join(dirname(STORE_BASE), 'handoffs')} yourself.`,
|
|
810
815
|
].join('\n'),
|
|
811
816
|
};
|
|
812
817
|
}
|
package/src/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
1
|
+
import { readFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import { join, dirname, parse as parsePath } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { atomicWrite } from './atomic.js';
|
|
@@ -85,6 +85,8 @@ export const paths = {
|
|
|
85
85
|
db: join(STORE_ROOT, 'index.db'),
|
|
86
86
|
routing: join(STORE_ROOT, 'ROUTING.md'),
|
|
87
87
|
config: join(STORE_ROOT, 'config.json'),
|
|
88
|
+
// Machine-scoped keys live beside every engagement rather than inside one.
|
|
89
|
+
machineConfig: join(STORE_BASE, 'config.json'),
|
|
88
90
|
typeDir: (type) => join(STORE_ROOT, 'notes', type),
|
|
89
91
|
archiveTypeDir: (type) => join(STORE_ROOT, 'notes', 'archive', type),
|
|
90
92
|
};
|
|
@@ -107,24 +109,41 @@ export const DEFAULTS = {
|
|
|
107
109
|
// from a checkout or copied into place, and both are legitimate installs.
|
|
108
110
|
export const LIST_KEYS = ['skillPaths'];
|
|
109
111
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
/** A malformed config must not take the store down. Absent and unreadable are equal. */
|
|
113
|
+
function readJson(file) {
|
|
114
|
+
if (!existsSync(file)) return {};
|
|
112
115
|
try {
|
|
113
|
-
|
|
114
|
-
const merged = { ...DEFAULTS, skillPaths: [] };
|
|
115
|
-
for (const [k, v] of Object.entries(raw)) {
|
|
116
|
-
if (k in DEFAULTS && typeof v === 'number' && Number.isFinite(v) && v > 0) merged[k] = v;
|
|
117
|
-
if (LIST_KEYS.includes(k) && Array.isArray(v)) {
|
|
118
|
-
merged[k] = v.filter((s) => typeof s === 'string' && s.trim());
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return merged;
|
|
116
|
+
return JSON.parse(readFileSync(file, 'utf8'));
|
|
122
117
|
} catch {
|
|
123
|
-
|
|
124
|
-
return { ...DEFAULTS, skillPaths: [] };
|
|
118
|
+
return {};
|
|
125
119
|
}
|
|
126
120
|
}
|
|
127
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Config comes from two files, split by what each key actually describes.
|
|
124
|
+
*
|
|
125
|
+
* Where the skills are installed is a fact about this machine. Every engagement
|
|
126
|
+
* shares one set of skill files, so registering them per engagement meant `compact`
|
|
127
|
+
* had nothing to regenerate after a switch and the recall description kept
|
|
128
|
+
* advertising the previous engagement's topics — into the agent's context, which is
|
|
129
|
+
* the worst place for it. Caps like the digest size really are per-store, and stay
|
|
130
|
+
* there. For the default engagement both files are the same path and nothing moves.
|
|
131
|
+
*/
|
|
132
|
+
export function loadConfig() {
|
|
133
|
+
const merged = { ...DEFAULTS, skillPaths: [] };
|
|
134
|
+
|
|
135
|
+
for (const [k, v] of Object.entries(readJson(paths.config))) {
|
|
136
|
+
if (k in DEFAULTS && typeof v === 'number' && Number.isFinite(v) && v > 0) merged[k] = v;
|
|
137
|
+
}
|
|
138
|
+
const machine = readJson(paths.machineConfig);
|
|
139
|
+
for (const k of LIST_KEYS) {
|
|
140
|
+
if (Array.isArray(machine[k])) {
|
|
141
|
+
merged[k] = machine[k].filter((s) => typeof s === 'string' && s.trim());
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return merged;
|
|
145
|
+
}
|
|
146
|
+
|
|
128
147
|
/**
|
|
129
148
|
* Merge a patch into config.json.
|
|
130
149
|
*
|
|
@@ -136,24 +155,37 @@ export function loadConfig() {
|
|
|
136
155
|
* cannot quietly become permanent state.
|
|
137
156
|
*/
|
|
138
157
|
export function saveConfig(patch) {
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
})()
|
|
147
|
-
: {};
|
|
148
|
-
|
|
149
|
-
const next = { ...current };
|
|
158
|
+
const sameFile = paths.config === paths.machineConfig;
|
|
159
|
+
const caps = readJson(paths.config);
|
|
160
|
+
const machine = sameFile ? caps : readJson(paths.machineConfig);
|
|
161
|
+
|
|
162
|
+
let capsDirty = false;
|
|
163
|
+
let machineDirty = false;
|
|
150
164
|
for (const [k, v] of Object.entries(patch || {})) {
|
|
151
|
-
if (k in DEFAULTS && typeof v === 'number' && Number.isFinite(v) && v > 0)
|
|
165
|
+
if (k in DEFAULTS && typeof v === 'number' && Number.isFinite(v) && v > 0) {
|
|
166
|
+
caps[k] = v;
|
|
167
|
+
capsDirty = true;
|
|
168
|
+
}
|
|
152
169
|
if (LIST_KEYS.includes(k) && Array.isArray(v)) {
|
|
153
|
-
|
|
170
|
+
machine[k] = [...new Set(v.filter((s) => typeof s === 'string' && s.trim()))].sort();
|
|
171
|
+
machineDirty = true;
|
|
154
172
|
}
|
|
155
173
|
}
|
|
156
174
|
|
|
157
|
-
|
|
158
|
-
|
|
175
|
+
if (sameFile) {
|
|
176
|
+
if (capsDirty || machineDirty) {
|
|
177
|
+
mkdirSync(dirname(paths.config), { recursive: true });
|
|
178
|
+
atomicWrite(paths.config, `${JSON.stringify(caps, null, 2)}\n`);
|
|
179
|
+
}
|
|
180
|
+
return { ...caps };
|
|
181
|
+
}
|
|
182
|
+
if (capsDirty) {
|
|
183
|
+
mkdirSync(dirname(paths.config), { recursive: true });
|
|
184
|
+
atomicWrite(paths.config, `${JSON.stringify(caps, null, 2)}\n`);
|
|
185
|
+
}
|
|
186
|
+
if (machineDirty) {
|
|
187
|
+
mkdirSync(dirname(paths.machineConfig), { recursive: true });
|
|
188
|
+
atomicWrite(paths.machineConfig, `${JSON.stringify(machine, null, 2)}\n`);
|
|
189
|
+
}
|
|
190
|
+
return { ...caps, ...Object.fromEntries(LIST_KEYS.map((k) => [k, machine[k]]).filter(([, v]) => v)) };
|
|
159
191
|
}
|
package/src/setup.js
CHANGED
|
@@ -11,8 +11,8 @@ import { toPromptFile, isGenerated } from './promptfile.js';
|
|
|
11
11
|
/**
|
|
12
12
|
* Installation, in Node rather than in two shell scripts.
|
|
13
13
|
*
|
|
14
|
-
* This is the single implementation behind
|
|
15
|
-
*
|
|
14
|
+
* This is the single implementation behind both entry points: `agent-memory setup`,
|
|
15
|
+
* and install.sh / install.ps1 which are thin wrappers over it. Writing it once
|
|
16
16
|
* matters because the machine that has to run it is a Windows desktop this was never
|
|
17
17
|
* developed on, and a PowerShell copy of this logic would drift silently.
|
|
18
18
|
*
|
|
@@ -207,8 +207,8 @@ export function setup({ compactFn } = {}) {
|
|
|
207
207
|
const existing = (loadConfig().skillPaths || []).filter((p) => existsSync(p));
|
|
208
208
|
saveConfig({ skillPaths: [...new Set([...existing, ...skillPaths])] });
|
|
209
209
|
|
|
210
|
-
// compact is passed in so this module does not pull the database
|
|
211
|
-
//
|
|
210
|
+
// compact is passed in so this module does not pull the database into memory just
|
|
211
|
+
// to make some symlinks.
|
|
212
212
|
const result = compactFn ? compactFn() : null;
|
|
213
213
|
return {
|
|
214
214
|
targets,
|
package/install.ps1
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
<#
|
|
2
|
-
.SYNOPSIS
|
|
3
|
-
Installs agent-memory and all three skills from a checkout.
|
|
4
|
-
|
|
5
|
-
.DESCRIPTION
|
|
6
|
-
`npm install -g .` does this on its own via the postinstall hook. This script
|
|
7
|
-
exists for two cases: installing straight from a clone without npm, and finishing
|
|
8
|
-
the job when a managed npm config sets ignore-scripts=true and silently skips it.
|
|
9
|
-
|
|
10
|
-
The linking itself lives in src\setup.js, not here. That is deliberate: a PowerShell
|
|
11
|
-
reimplementation could only be tested on Windows, and the machine this was written
|
|
12
|
-
on is not Windows. One implementation, three entry points, no drift.
|
|
13
|
-
|
|
14
|
-
Skills are linked into both agent directories:
|
|
15
|
-
%USERPROFILE%\.agents\skills\<name> -> read by GitHub Copilot in every window
|
|
16
|
-
%USERPROFILE%\.claude\skills\<name> -> read by Claude Code
|
|
17
|
-
|
|
18
|
-
Directory junctions are used, which need neither admin rights nor Developer Mode.
|
|
19
|
-
They fail on a network-backed profile (FSLogix, roaming), and setup falls back to
|
|
20
|
-
copying and says so.
|
|
21
|
-
|
|
22
|
-
.EXAMPLE
|
|
23
|
-
powershell -ExecutionPolicy Bypass -File .\install.ps1
|
|
24
|
-
#>
|
|
25
|
-
|
|
26
|
-
$ErrorActionPreference = 'Stop'
|
|
27
|
-
|
|
28
|
-
$source = $PSScriptRoot
|
|
29
|
-
|
|
30
|
-
$node = Get-Command node -ErrorAction SilentlyContinue
|
|
31
|
-
if (-not $node) {
|
|
32
|
-
Write-Error "node not found on PATH. agent-memory needs Node >= 22.5."
|
|
33
|
-
exit 1
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
& node (Join-Path $source 'src\cli.js') setup
|
|
37
|
-
|
|
38
|
-
Write-Host ""
|
|
39
|
-
Write-Host "Linking the CLI" -ForegroundColor Cyan
|
|
40
|
-
# npm writes its warnings to stderr, and `2>&1` turns each one into an ErrorRecord,
|
|
41
|
-
# which $ErrorActionPreference = 'Stop' then treats as terminating. A managed npm
|
|
42
|
-
# config makes that certain rather than unlikely: an unknown key such as `always-auth`
|
|
43
|
-
# produces a warning on every single npm invocation, so this step could never succeed
|
|
44
|
-
# on the desktops this script exists for. It aborted the whole install — no fallback
|
|
45
|
-
# message, no doctor, no closing instructions — over a warning about an unrelated
|
|
46
|
-
# config key. Scope the preference to this one call.
|
|
47
|
-
$previousPreference = $ErrorActionPreference
|
|
48
|
-
$ErrorActionPreference = 'Continue'
|
|
49
|
-
try {
|
|
50
|
-
& npm install -g $source 2>&1 | Out-Null
|
|
51
|
-
$npmExit = $LASTEXITCODE
|
|
52
|
-
} catch {
|
|
53
|
-
$npmExit = 1
|
|
54
|
-
} finally {
|
|
55
|
-
$ErrorActionPreference = $previousPreference
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if ($npmExit -eq 0) {
|
|
59
|
-
Write-Host " [npm] agent-memory installed globally" -ForegroundColor Green
|
|
60
|
-
} else {
|
|
61
|
-
# A global install failing on a managed desktop is common and not worth aborting
|
|
62
|
-
# on. The skills are already linked; this one step can be finished by hand.
|
|
63
|
-
Write-Host " [npm] global install failed. Run this yourself:" -ForegroundColor Yellow
|
|
64
|
-
Write-Host " npm install -g `"$source`"" -ForegroundColor Yellow
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
Write-Host ""
|
|
68
|
-
& node (Join-Path $source 'src\cli.js') doctor
|
|
69
|
-
|
|
70
|
-
Write-Host ""
|
|
71
|
-
Write-Host "Installed. Restart VS Code, then try /recall, /remember, or /handoff." -ForegroundColor Cyan
|
package/install.sh
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Installs agent-memory and all three skills from a checkout, on macOS/Linux.
|
|
3
|
-
#
|
|
4
|
-
# `npm install -g .` does this on its own via the postinstall hook. This script
|
|
5
|
-
# exists for two cases: installing straight from a clone without npm, and finishing
|
|
6
|
-
# the job when a managed npm config sets ignore-scripts=true and silently skips it.
|
|
7
|
-
#
|
|
8
|
-
# The linking itself lives in src/setup.js, not here. One implementation, three entry
|
|
9
|
-
# points, so this script and its PowerShell twin cannot drift from each other.
|
|
10
|
-
set -euo pipefail
|
|
11
|
-
|
|
12
|
-
source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
-
|
|
14
|
-
if ! command -v node >/dev/null 2>&1; then
|
|
15
|
-
echo "node not found on PATH. agent-memory needs Node >= 22.5." >&2
|
|
16
|
-
exit 1
|
|
17
|
-
fi
|
|
18
|
-
|
|
19
|
-
node "$source_dir/src/cli.js" setup
|
|
20
|
-
|
|
21
|
-
echo
|
|
22
|
-
echo "Linking the CLI"
|
|
23
|
-
if npm install -g "$source_dir" >/dev/null 2>&1; then
|
|
24
|
-
echo " [npm] agent-memory installed globally"
|
|
25
|
-
else
|
|
26
|
-
# A global install needing sudo is common and is not worth aborting on. The skills
|
|
27
|
-
# are already linked, and the user can finish this one step by hand.
|
|
28
|
-
echo " [npm] global install failed (permissions?). Run this yourself:"
|
|
29
|
-
echo " npm install -g \"$source_dir\""
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
echo
|
|
33
|
-
node "$source_dir/src/cli.js" doctor || true
|
|
34
|
-
|
|
35
|
-
echo
|
|
36
|
-
echo "Installed. Restart VS Code, then try /recall, /remember, or /handoff."
|
package/scripts/postinstall.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Link the skills when the package is installed.
|
|
4
|
-
*
|
|
5
|
-
* This must never fail an install. A missing symlink is a nuisance; an `npm install`
|
|
6
|
-
* that exits non-zero on a managed desktop is the kind of thing that gets a tool
|
|
7
|
-
* banned. Every failure here is reported and swallowed, and `agent-memory setup`
|
|
8
|
-
* remains available to finish the job by hand.
|
|
9
|
-
*
|
|
10
|
-
* Note that managed npm configurations often set `ignore-scripts=true`, in which case
|
|
11
|
-
* this file never runs and nothing warns you. That is precisely why the same work is
|
|
12
|
-
* exposed as a command, and why `doctor` names it.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const say = (msg) => process.stdout.write(`${msg}\n`);
|
|
16
|
-
|
|
17
|
-
if (process.env.AGENT_MEMORY_SKIP_POSTINSTALL) {
|
|
18
|
-
process.exit(0);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const [maj, min] = process.versions.node.split('.').map((s) => Number.parseInt(s, 10));
|
|
23
|
-
if (maj < 22 || (maj === 22 && min < 5)) {
|
|
24
|
-
say(`agent-memory: Node ${process.versions.node} is too old; needs >= 22.5 for node:sqlite.`);
|
|
25
|
-
say('agent-memory: skills not linked. Upgrade Node, then run: agent-memory setup');
|
|
26
|
-
process.exit(0);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const { setup } = await import('../src/setup.js');
|
|
30
|
-
const { compact } = await import('../src/compact.js');
|
|
31
|
-
const r = setup({ compactFn: () => compact() });
|
|
32
|
-
|
|
33
|
-
const links = r.installed.filter((s) => s.mode === 'link').length;
|
|
34
|
-
const copies = r.copies.length;
|
|
35
|
-
say(`agent-memory: linked ${links} skill${links === 1 ? '' : 's'}${copies ? `, copied ${copies}` : ''}.`);
|
|
36
|
-
say(`agent-memory: ${r.notes} notes indexed. Restart VS Code, then try /recall.`);
|
|
37
|
-
if (copies) {
|
|
38
|
-
say('agent-memory: copies happen on network-backed profiles; re-run `agent-memory setup` after upgrades.');
|
|
39
|
-
}
|
|
40
|
-
} catch (err) {
|
|
41
|
-
say(`agent-memory: automatic setup did not complete (${err.message}).`);
|
|
42
|
-
say('agent-memory: run `agent-memory setup` to finish. Nothing else is affected.');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
process.exit(0);
|
package/uninstall.ps1
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
<#
|
|
2
|
-
.SYNOPSIS
|
|
3
|
-
Removes the skills and the CLI, in the order that is recoverable.
|
|
4
|
-
|
|
5
|
-
.DESCRIPTION
|
|
6
|
-
npm will not enforce that order and gets it wrong on its own: `npm uninstall -g`
|
|
7
|
-
deletes the package and leaves one link per skill per agent pointing at nothing,
|
|
8
|
-
which every one of those agents still tries to load. By then the binary that would
|
|
9
|
-
have cleaned them up is gone too, so tooling cannot fix it. This unlinks first and
|
|
10
|
-
removes the package second.
|
|
11
|
-
|
|
12
|
-
Your notes are never touched. They are plain markdown under
|
|
13
|
-
%USERPROFILE%\.agents\memory, they outlive the tool that indexed them, and removing
|
|
14
|
-
them is your call, not this script's.
|
|
15
|
-
|
|
16
|
-
.EXAMPLE
|
|
17
|
-
powershell -ExecutionPolicy Bypass -File .\uninstall.ps1
|
|
18
|
-
#>
|
|
19
|
-
|
|
20
|
-
# Not 'Stop': a half-finished uninstall is worse than a reported failure, so each step
|
|
21
|
-
# is allowed to fail and say so.
|
|
22
|
-
$ErrorActionPreference = 'Continue'
|
|
23
|
-
|
|
24
|
-
$source = $PSScriptRoot
|
|
25
|
-
|
|
26
|
-
$node = Get-Command node -ErrorAction SilentlyContinue
|
|
27
|
-
if (-not $node) {
|
|
28
|
-
Write-Error "node not found on PATH. agent-memory needs Node >= 22.5."
|
|
29
|
-
exit 1
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
Write-Host "Removing skills" -ForegroundColor Cyan
|
|
33
|
-
# Run from the checkout rather than the installed binary, so this still works when the
|
|
34
|
-
# global package is already gone.
|
|
35
|
-
& node (Join-Path $source 'src\cli.js') uninstall
|
|
36
|
-
|
|
37
|
-
Write-Host ""
|
|
38
|
-
Write-Host "Removing the CLI" -ForegroundColor Cyan
|
|
39
|
-
try {
|
|
40
|
-
& npm uninstall -g '@vib795/agent-memory' 2>&1 | Out-Null
|
|
41
|
-
$npmExit = $LASTEXITCODE
|
|
42
|
-
} catch {
|
|
43
|
-
$npmExit = 1
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if ($npmExit -eq 0) {
|
|
47
|
-
Write-Host " [npm] package removed" -ForegroundColor Green
|
|
48
|
-
} else {
|
|
49
|
-
Write-Host " [npm] not removed. It may not be installed globally:" -ForegroundColor Yellow
|
|
50
|
-
Write-Host " npm uninstall -g `"@vib795/agent-memory`"" -ForegroundColor Yellow
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
Write-Host ""
|
|
54
|
-
Write-Host "Done. Your notes are untouched." -ForegroundColor Cyan
|
package/uninstall.sh
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Removes the skills and the CLI, in the order that is recoverable.
|
|
3
|
-
#
|
|
4
|
-
# npm will not enforce that order and gets it wrong on its own: `npm uninstall -g`
|
|
5
|
-
# deletes the package and leaves one link per skill per agent pointing at nothing,
|
|
6
|
-
# which every one of those agents still tries to load. By then the binary that would
|
|
7
|
-
# have cleaned them up is gone too, so tooling cannot fix it. Unlink first, remove
|
|
8
|
-
# the package second.
|
|
9
|
-
#
|
|
10
|
-
# Your notes are never touched. They are plain markdown under ~/.agents/memory, they
|
|
11
|
-
# outlive the tool that indexed them, and removing them is your call, not this script's.
|
|
12
|
-
#
|
|
13
|
-
# No `set -e`: a half-finished uninstall is worse than a reported failure, so each
|
|
14
|
-
# step is allowed to fail and say so.
|
|
15
|
-
set -uo pipefail
|
|
16
|
-
|
|
17
|
-
source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
18
|
-
|
|
19
|
-
if ! command -v node >/dev/null 2>&1; then
|
|
20
|
-
echo "node not found on PATH. agent-memory needs Node >= 22.5." >&2
|
|
21
|
-
exit 1
|
|
22
|
-
fi
|
|
23
|
-
|
|
24
|
-
echo "Removing skills"
|
|
25
|
-
# Run from the checkout rather than the installed binary, so this still works when
|
|
26
|
-
# the global package is already gone.
|
|
27
|
-
node "$source_dir/src/cli.js" uninstall
|
|
28
|
-
|
|
29
|
-
echo
|
|
30
|
-
echo "Removing the CLI"
|
|
31
|
-
if npm uninstall -g @vib795/agent-memory >/dev/null 2>&1; then
|
|
32
|
-
echo " [npm] package removed"
|
|
33
|
-
else
|
|
34
|
-
echo " [npm] not removed. It may not be installed globally, or may need sudo:"
|
|
35
|
-
echo " npm uninstall -g @vib795/agent-memory"
|
|
36
|
-
fi
|
|
37
|
-
|
|
38
|
-
echo
|
|
39
|
-
echo "Done. Your notes are untouched at ${AGENT_MEMORY_HOME:-$HOME/.agents/memory}."
|
package/update.ps1
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<#
|
|
2
|
-
.SYNOPSIS
|
|
3
|
-
Updates a clone install: pull, then re-run the installer.
|
|
4
|
-
|
|
5
|
-
.DESCRIPTION
|
|
6
|
-
The install logic is deliberately not repeated here. install.ps1 already relinks the
|
|
7
|
-
skills, relinks the CLI and runs doctor; an update is exactly that plus a pull, and
|
|
8
|
-
writing it a second time is how the two drift.
|
|
9
|
-
|
|
10
|
-
Re-running setup is not optional on an upgrade. Prompt files are copies rather than
|
|
11
|
-
links, so VS Code keeps reading the old text until something rewrites it.
|
|
12
|
-
|
|
13
|
-
.EXAMPLE
|
|
14
|
-
powershell -ExecutionPolicy Bypass -File .\update.ps1
|
|
15
|
-
#>
|
|
16
|
-
|
|
17
|
-
$ErrorActionPreference = 'Stop'
|
|
18
|
-
|
|
19
|
-
$source = $PSScriptRoot
|
|
20
|
-
|
|
21
|
-
if (-not (Test-Path (Join-Path $source '.git'))) {
|
|
22
|
-
Write-Host "This is not a git checkout, so there is nothing to pull." -ForegroundColor Yellow
|
|
23
|
-
Write-Host "If you installed from npm, update with:" -ForegroundColor Yellow
|
|
24
|
-
Write-Host " npm install -g @vib795/agent-memory@latest" -ForegroundColor Yellow
|
|
25
|
-
Write-Host " agent-memory setup" -ForegroundColor Yellow
|
|
26
|
-
exit 1
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
Write-Host "Pulling" -ForegroundColor Cyan
|
|
30
|
-
# git writes ordinary progress to stderr, and `Stop` would treat that as terminating.
|
|
31
|
-
$previousPreference = $ErrorActionPreference
|
|
32
|
-
$ErrorActionPreference = 'Continue'
|
|
33
|
-
try {
|
|
34
|
-
& git -C $source pull --ff-only 2>&1 | Write-Host
|
|
35
|
-
$gitExit = $LASTEXITCODE
|
|
36
|
-
} finally {
|
|
37
|
-
$ErrorActionPreference = $previousPreference
|
|
38
|
-
}
|
|
39
|
-
if ($gitExit -ne 0) {
|
|
40
|
-
Write-Error "git pull failed. Resolve that first, then run this again."
|
|
41
|
-
exit 1
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
Write-Host ""
|
|
45
|
-
& powershell -ExecutionPolicy Bypass -File (Join-Path $source 'install.ps1')
|
package/update.sh
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Updates a clone install: pull, then re-run the installer.
|
|
3
|
-
#
|
|
4
|
-
# The install logic is deliberately not repeated here. install.sh already relinks the
|
|
5
|
-
# skills, relinks the CLI and runs doctor; an update is exactly that plus a pull, and
|
|
6
|
-
# writing it a second time is how the two drift.
|
|
7
|
-
#
|
|
8
|
-
# Re-running setup is not optional on an upgrade. Prompt files are copies rather than
|
|
9
|
-
# links, so an editor keeps reading the old text until something rewrites it.
|
|
10
|
-
set -euo pipefail
|
|
11
|
-
|
|
12
|
-
source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
-
|
|
14
|
-
if [ ! -d "$source_dir/.git" ]; then
|
|
15
|
-
echo "This is not a git checkout, so there is nothing to pull." >&2
|
|
16
|
-
echo "If you installed from npm, update with:" >&2
|
|
17
|
-
echo " npm install -g @vib795/agent-memory@latest" >&2
|
|
18
|
-
echo " agent-memory setup" >&2
|
|
19
|
-
exit 1
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
echo "Pulling"
|
|
23
|
-
git -C "$source_dir" pull --ff-only
|
|
24
|
-
|
|
25
|
-
echo
|
|
26
|
-
exec "$source_dir/install.sh"
|