myagentmemory 0.4.16 → 0.4.17
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 +1 -0
- package/README.md +17 -4
- package/dist/cli-spec.d.ts +1 -1
- package/dist/cli-spec.js +14 -2
- package/dist/cli.js +107 -42
- package/dist/plugin-bootstrap.js +2 -2
- package/dist/plugin-host.d.ts +18 -0
- package/dist/plugin-runtime.d.ts +8 -1
- package/dist/plugin-runtime.js +39 -0
- package/dist/plugin-service.js +36 -39
- package/docs/official-plugin-bootstrap.md +29 -21
- package/package.json +1 -1
- package/src/cli-spec.ts +14 -2
- package/src/cli.ts +112 -51
- package/src/plugin-bootstrap.ts +2 -2
- package/src/plugin-host.ts +20 -0
- package/src/plugin-runtime.ts +64 -0
- package/src/plugin-service.ts +39 -40
package/dist/plugin-service.js
CHANGED
|
@@ -18,29 +18,27 @@ const MISSING_ENTITLEMENT = {
|
|
|
18
18
|
state: "missing",
|
|
19
19
|
features: [],
|
|
20
20
|
capabilities: {},
|
|
21
|
-
reason: "
|
|
21
|
+
reason: "Install the no-account Pro preview to activate local recall and learning",
|
|
22
22
|
};
|
|
23
23
|
function cloneEntitlement(value) {
|
|
24
24
|
return structuredClone(value);
|
|
25
25
|
}
|
|
26
|
-
function freeEntitlement(
|
|
26
|
+
function freeEntitlement() {
|
|
27
27
|
return {
|
|
28
28
|
plan: "free",
|
|
29
29
|
state: "active",
|
|
30
30
|
features: ["session-intelligence", "web-console"],
|
|
31
31
|
capabilities: {
|
|
32
32
|
"session-index": { enabled: true },
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
learning: { enabled: true },
|
|
33
|
+
recall: { enabled: true, quota: { limit: 10, window: "day", scope: "device" } },
|
|
34
|
+
"session-worker": { enabled: false },
|
|
35
|
+
learning: { enabled: true, quota: { limit: 1, window: "day", scope: "device" } },
|
|
38
36
|
"retrieval-evaluation": { enabled: true },
|
|
39
37
|
"operational-metrics": { enabled: true },
|
|
40
38
|
"web-console": { enabled: true },
|
|
41
39
|
"memory-explorer": { enabled: true },
|
|
42
40
|
},
|
|
43
|
-
reason:
|
|
41
|
+
reason: "Free preview: 10 recalls and 1 learning scan per local day; indexing and dashboard access remain available",
|
|
44
42
|
};
|
|
45
43
|
}
|
|
46
44
|
function isEmail(value) {
|
|
@@ -346,41 +344,27 @@ export class TemporaryPluginBackend {
|
|
|
346
344
|
this.artifactOrigin = options.artifactOrigin ?? ARTIFACT_ORIGIN;
|
|
347
345
|
this.fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
348
346
|
this.openUrl = options.openUrl ?? openLoopbackUrl;
|
|
349
|
-
this.activate = options.activate ?? (() =>
|
|
347
|
+
this.activate = options.activate ?? (async () => `am_install_${randomBytes(24).toString("base64url")}`);
|
|
350
348
|
}
|
|
351
349
|
async getLocalEntitlement() {
|
|
352
350
|
const activation = this.readActivation();
|
|
353
|
-
return activation ? freeEntitlement(
|
|
351
|
+
return activation ? freeEntitlement() : cloneEntitlement(MISSING_ENTITLEMENT);
|
|
354
352
|
}
|
|
355
353
|
async resolveAccess(request) {
|
|
356
354
|
const activation = this.readActivation();
|
|
357
|
-
|
|
358
|
-
if (!email) {
|
|
359
|
-
if (!request.allowAuthentication)
|
|
360
|
-
return {
|
|
361
|
-
kind: "auth_required",
|
|
362
|
-
entitlement: cloneEntitlement(MISSING_ENTITLEMENT),
|
|
363
|
-
nextAction: {
|
|
364
|
-
kind: "authenticate",
|
|
365
|
-
url: "https://jayzeng.github.io/agentmemory/",
|
|
366
|
-
message: "Run plugin install in an interactive terminal to enter an email address",
|
|
367
|
-
},
|
|
368
|
-
};
|
|
369
|
-
email = await this.activate();
|
|
370
|
-
}
|
|
355
|
+
const installationId = activation?.installationId ?? (await this.activate());
|
|
371
356
|
const response = await this.request(`${this.apiOrigin}/v1/plugin/access`, {
|
|
372
357
|
method: "POST",
|
|
373
358
|
headers: { "Content-Type": "application/json" },
|
|
374
359
|
body: JSON.stringify({
|
|
375
|
-
schemaVersion:
|
|
376
|
-
|
|
360
|
+
schemaVersion: 2,
|
|
361
|
+
installationId,
|
|
377
362
|
bundleId: request.bundleId,
|
|
378
363
|
installedVersion: request.installedVersion ?? null,
|
|
379
364
|
coreVersion: this.coreVersion,
|
|
380
365
|
channel: request.channel,
|
|
381
366
|
platform: process.platform,
|
|
382
367
|
architecture: process.arch,
|
|
383
|
-
consentVersion: "activation-v2",
|
|
384
368
|
}),
|
|
385
369
|
});
|
|
386
370
|
const value = (await readJson(response));
|
|
@@ -389,14 +373,20 @@ export class TemporaryPluginBackend {
|
|
|
389
373
|
throw new PluginBootstrapFailure("service_response_invalid", "The access response omitted its artifact grant");
|
|
390
374
|
if (typeof value.usageCredential !== "string" || !ACTIVATION_CREDENTIAL.test(value.usageCredential))
|
|
391
375
|
throw new PluginBootstrapFailure("service_response_invalid", "The access response omitted its usage credential");
|
|
392
|
-
const
|
|
376
|
+
const recallQuota = value.entitlement.capabilities.recall?.quota;
|
|
377
|
+
const learningQuota = value.entitlement.capabilities.learning?.quota;
|
|
393
378
|
if (value.entitlement.plan !== "free" ||
|
|
394
379
|
value.entitlement.state !== "active" ||
|
|
395
|
-
!
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
380
|
+
!recallQuota ||
|
|
381
|
+
recallQuota.scope !== "device" ||
|
|
382
|
+
recallQuota.window !== "day" ||
|
|
383
|
+
!learningQuota ||
|
|
384
|
+
learningQuota.scope !== "device" ||
|
|
385
|
+
learningQuota.window !== "day" ||
|
|
386
|
+
value.entitlement.capabilities["session-index"]?.enabled !== true ||
|
|
387
|
+
value.entitlement.capabilities["web-console"]?.enabled !== true)
|
|
388
|
+
throw new PluginBootstrapFailure("service_response_invalid", "The free preview policy is invalid");
|
|
389
|
+
this.writeActivation(installationId, value.usageCredential, 1);
|
|
400
390
|
return { kind: "granted", entitlement: value.entitlement, artifactGrant: value.artifactGrant };
|
|
401
391
|
}
|
|
402
392
|
async reserveSession(operationId) {
|
|
@@ -451,8 +441,9 @@ export class TemporaryPluginBackend {
|
|
|
451
441
|
if (!stat.isFile() || stat.isSymbolicLink() || (process.platform !== "win32" && (stat.mode & 0o077) !== 0))
|
|
452
442
|
return null;
|
|
453
443
|
const value = JSON.parse(fs.readFileSync(activationPath, "utf-8"));
|
|
454
|
-
if (value.schemaVersion !==
|
|
455
|
-
|
|
444
|
+
if (value.schemaVersion !== 3 ||
|
|
445
|
+
typeof value.installationId !== "string" ||
|
|
446
|
+
!/^am_install_[A-Za-z0-9_-]{32}$/.test(value.installationId) ||
|
|
456
447
|
!Number.isFinite(Date.parse(value.activatedAt)) ||
|
|
457
448
|
!ACTIVATION_CREDENTIAL.test(value.usageCredential) ||
|
|
458
449
|
!Number.isSafeInteger(value.dailySessionLimit) ||
|
|
@@ -465,9 +456,9 @@ export class TemporaryPluginBackend {
|
|
|
465
456
|
return null;
|
|
466
457
|
}
|
|
467
458
|
}
|
|
468
|
-
writeActivation(
|
|
469
|
-
if (
|
|
470
|
-
throw new PluginBootstrapFailure("
|
|
459
|
+
writeActivation(installationId, usageCredential, dailySessionLimit) {
|
|
460
|
+
if (!/^am_install_[A-Za-z0-9_-]{32}$/.test(installationId))
|
|
461
|
+
throw new PluginBootstrapFailure("activation_failed", "The installation identifier is invalid");
|
|
471
462
|
if (!ACTIVATION_CREDENTIAL.test(usageCredential))
|
|
472
463
|
throw new PluginBootstrapFailure("activation_failed", "The activation credential is invalid");
|
|
473
464
|
if (!Number.isSafeInteger(dailySessionLimit) || dailySessionLimit <= 0 || dailySessionLimit > 10_000)
|
|
@@ -484,7 +475,13 @@ export class TemporaryPluginBackend {
|
|
|
484
475
|
if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink())
|
|
485
476
|
throw new PluginBootstrapFailure("activation_path_invalid", "The plugin activation directory is unsafe");
|
|
486
477
|
const temporary = `${target}.tmp-${process.pid}-${randomUUID()}`;
|
|
487
|
-
fs.writeFileSync(temporary, `${JSON.stringify({
|
|
478
|
+
fs.writeFileSync(temporary, `${JSON.stringify({
|
|
479
|
+
schemaVersion: 3,
|
|
480
|
+
installationId,
|
|
481
|
+
activatedAt: new Date().toISOString(),
|
|
482
|
+
usageCredential,
|
|
483
|
+
dailySessionLimit,
|
|
484
|
+
}, null, 2)}\n`, { mode: 0o600, flag: "wx" });
|
|
488
485
|
fs.renameSync(temporary, target);
|
|
489
486
|
}
|
|
490
487
|
async sessionUsage(action, operationId) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Status
|
|
4
4
|
|
|
5
|
-
Accepted design on 2026-08-16 and revised on 2026-08-17. The public core implements host types,
|
|
5
|
+
Accepted design on 2026-08-16 and revised on 2026-08-17. The public core implements host types, anonymous preview activation, live catalog and artifact retrieval, Ed25519 release verification, bounded package validation, transactional install, bundle health checks, paid-command dispatch, and SessionStart hook dispatch. The free preview grants 10 device-local recalls and one device-local learning scan per local day while keeping indexing and Memory Dashboard visibility available. Account authentication, payment, renewal, and account management remain deferred.
|
|
6
6
|
|
|
7
7
|
The public `agentmemory` repository and `myagentmemory` npm package remain the free, MIT-licensed core. The public bootstrap client and host contracts are also MIT-licensed. Official commercial implementations and browser assets are built and distributed separately from the private `agent-memory-plugin` workspace under their own terms. Pricing, the billing provider, device limits, offline-grace duration, and Enterprise contract terms are intentionally not decided here. The temporary beta currently uses allowlisted `*.agentmemory.paperpilot.me` service origins; changing those origins is a public-client release change.
|
|
8
8
|
|
|
@@ -10,10 +10,10 @@ The public `agentmemory` repository and `myagentmemory` npm package remain the f
|
|
|
10
10
|
|
|
11
11
|
The public core will provide a small bootstrap and host surface for signed first-party plugins. It will not contain paid implementations, browser assets, commercial entitlement logic, or a general third-party marketplace.
|
|
12
12
|
|
|
13
|
-
The primary
|
|
13
|
+
The primary product-facing command is:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
agent-memory
|
|
16
|
+
agent-memory pro install
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
`plugin install` is an idempotent reconcile operation:
|
|
@@ -23,11 +23,11 @@ agent-memory plugin install
|
|
|
23
23
|
| Plugin absent | Active or grace | Install the compatible signed bundle |
|
|
24
24
|
| Plugin older than the selected release | Active or grace | Upgrade atomically |
|
|
25
25
|
| Plugin current | Active or grace | Report that it is current |
|
|
26
|
-
| Any | Missing |
|
|
26
|
+
| Any | Missing | Request an anonymous free-preview entitlement and signed artifact grant |
|
|
27
27
|
| Any | Expired | Direct the user to renewal; leave core available |
|
|
28
28
|
| Incompatible bundle | Any | Leave the current version untouched and explain the required core version |
|
|
29
29
|
|
|
30
|
-
An absent plugin cannot activate itself. The public bootstrap
|
|
30
|
+
An absent plugin cannot activate itself. The public bootstrap creates a random installation identifier, obtains a server-issued free-preview policy and short-lived artifact grant, and verifies the release and artifact. A mode-0600 activation record is persisted only after the service accepts the request. After installation, the public host reconstructs the free capability policy in core code and checks required capabilities before commands and hooks. Signed long-lived paid entitlements can extend this record when authentication and payment ship.
|
|
31
31
|
|
|
32
32
|
## Ownership boundary
|
|
33
33
|
|
|
@@ -67,6 +67,12 @@ Core memory operations must continue to work when the service is unreachable, a
|
|
|
67
67
|
### Bootstrap commands
|
|
68
68
|
|
|
69
69
|
```text
|
|
70
|
+
agent-memory pro
|
|
71
|
+
agent-memory pro install
|
|
72
|
+
agent-memory pro status
|
|
73
|
+
agent-memory pro upgrade
|
|
74
|
+
agent-memory pro manage
|
|
75
|
+
|
|
70
76
|
agent-memory plugin
|
|
71
77
|
agent-memory plugin list
|
|
72
78
|
agent-memory plugin status
|
|
@@ -76,6 +82,8 @@ agent-memory plugin uninstall [--yes]
|
|
|
76
82
|
agent-memory plugin manage [--no-browser]
|
|
77
83
|
```
|
|
78
84
|
|
|
85
|
+
The `pro` namespace is the user-facing surface. The `plugin` namespace remains supported for low-level administration and compatibility.
|
|
86
|
+
|
|
79
87
|
- `plugin` with no subcommand prints a discovery summary and the next relevant command.
|
|
80
88
|
- `list` reports known official plugins and whether each is installed and available. It does not download artifacts or inspect memory.
|
|
81
89
|
- `status` is read-only. It reports the installed bundle, selected channel, compatibility, entitlement state, and update availability.
|
|
@@ -84,7 +92,7 @@ agent-memory plugin manage [--no-browser]
|
|
|
84
92
|
- `uninstall` removes executable plugin material and the active receipt. It preserves core memory, plugin state, and the permission-restricted activation credential.
|
|
85
93
|
- `manage` remains unavailable until authenticated account and billing management exists.
|
|
86
94
|
|
|
87
|
-
Installed plugins contribute top-level commands
|
|
95
|
+
Installed plugins contribute top-level commands including `recall` and `learn`; `dashboard` is a product-facing alias for the lower-level `web` command. Bootstrap command names are reserved by the core and cannot be replaced by a plugin.
|
|
88
96
|
|
|
89
97
|
The current private compatibility CLI uses `plugin install` and `plugin uninstall` for skill files only. During migration, those meanings move to `install-skills --plugin-only` and `uninstall-skills --plugin-only`; the bootstrap command names above become authoritative.
|
|
90
98
|
|
|
@@ -93,13 +101,13 @@ The current private compatibility CLI uses `plugin install` and `plugin uninstal
|
|
|
93
101
|
After a successful interactive `agent-memory init`, the core may print one informational line:
|
|
94
102
|
|
|
95
103
|
```text
|
|
96
|
-
|
|
97
|
-
Run: agent-memory
|
|
104
|
+
Core remembers what you save. Pro learns from what you do.
|
|
105
|
+
Run: agent-memory pro install
|
|
98
106
|
```
|
|
99
107
|
|
|
100
|
-
Top-level help includes
|
|
108
|
+
Top-level help includes a Pro section. Human-readable `status` may include the same recommendation while Pro is not installed. Routine `context`, `read`, `write`, `search`, and scratchpad commands never show commercial prompts.
|
|
101
109
|
|
|
102
|
-
The
|
|
110
|
+
The free preview does not open a browser or request identity. Browsers remain restricted to explicit `dashboard`, future `pro manage`, and future paid upgrade/authentication flows. Non-interactive and `--json` installs use the same anonymous access request and still fail closed when the commercial service is unavailable.
|
|
103
111
|
|
|
104
112
|
### Machine-readable output
|
|
105
113
|
|
|
@@ -133,17 +141,17 @@ Every bootstrap command supports `--json` and emits one JSON document with a ver
|
|
|
133
141
|
|
|
134
142
|
`result` is one of `not_installed`, `installed`, `upgraded`, `current`, `update_available`, `uninstalled`, `auth_required`, `renewal_required`, or `unavailable`. Failures use `ok: false` plus a stable `error.code` and redacted `error.message`. Output must never contain access tokens, download credentials, signed entitlement contents, local memory paths, or URLs containing bearer credentials.
|
|
135
143
|
|
|
136
|
-
##
|
|
144
|
+
## Anonymous free-preview flow
|
|
137
145
|
|
|
138
|
-
1. `agent-memory
|
|
139
|
-
2. The CLI
|
|
140
|
-
3.
|
|
141
|
-
4. The
|
|
142
|
-
5.
|
|
146
|
+
1. `agent-memory pro install` creates a random installation identifier locally when no activation record exists.
|
|
147
|
+
2. The CLI sends that identifier plus core, installed-bundle, platform, architecture, and release-channel fields to the private control plane. It sends no email, memory, session content, query, repository path, raw agent session identifier, IP address, or user-agent string.
|
|
148
|
+
3. The service stores the pseudonymous identifier and only the hash of a random compatibility credential, then returns a free-preview capability policy and short-lived object-bound artifact grant.
|
|
149
|
+
4. The CLI validates the explicit free policy: local indexing and Memory Dashboard access, 10 device-local recalls per day, one device-local learning scan per day, and no free automatic background worker.
|
|
150
|
+
5. Only then does the CLI atomically write a mode-0600 activation record.
|
|
143
151
|
6. The CLI verifies the Ed25519-signed release plus package digest and limits, imports it for health checks, and atomically activates the receipt.
|
|
144
|
-
7.
|
|
152
|
+
7. Device-local quota operations reserve before work, commit after useful work, and release on abstention or failure. A zero-result recall does not consume allowance.
|
|
145
153
|
|
|
146
|
-
|
|
154
|
+
Authentication, payment, renewal, account management, and signed paid entitlements are not implemented yet.
|
|
147
155
|
|
|
148
156
|
## Future authentication and purchase flow
|
|
149
157
|
|
|
@@ -163,12 +171,12 @@ An Enterprise administrator may pre-provision an organization entitlement or man
|
|
|
163
171
|
|
|
164
172
|
The service exposes:
|
|
165
173
|
|
|
166
|
-
- `POST /v1/plugin/access` for
|
|
167
|
-
- `POST /v1/plugin/sessions/reserve|commit|release` for
|
|
174
|
+
- `POST /v1/plugin/access` for an anonymous free-preview policy, compatibility credential, and short-lived artifact grant;
|
|
175
|
+
- `POST /v1/plugin/sessions/reserve|commit|release` for migration compatibility with activation-v2 clients;
|
|
168
176
|
- `GET /v1/plugin/releases` for an Ed25519-signed release selected from the private R2 catalog;
|
|
169
177
|
- `GET|HEAD /v1/artifacts/download` for the exact content-addressed object authorized by the bearer grant.
|
|
170
178
|
|
|
171
|
-
The access request contains
|
|
179
|
+
The access request contains a random installation identifier plus the bounded core, bundle, platform, architecture, and release-channel fields described above. Application payloads contain no email, memory content, search query, session content, path, repository name, raw agent session identifier, qmd data, IP address, or user-agent string. The activation database stores neither IP addresses nor user-agent strings. Future authenticated service responsibilities include:
|
|
172
180
|
|
|
173
181
|
- create and poll a device authorization;
|
|
174
182
|
- read the authenticated principal's effective entitlement;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myagentmemory",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.17",
|
|
4
4
|
"description": "agentmemory (agent-memory) is persistent memory for coding agents (Claude Code, OpenAI Codex, Cursor, Agent) with qmd-powered semantic search across daily logs, long-term memory, and scratchpad",
|
|
5
5
|
"main": "./dist/core.js",
|
|
6
6
|
"types": "./dist/core.d.ts",
|
package/src/cli-spec.ts
CHANGED
|
@@ -23,6 +23,10 @@ export const COMMANDS = [
|
|
|
23
23
|
"install-hooks",
|
|
24
24
|
"uninstall-hooks",
|
|
25
25
|
"completion",
|
|
26
|
+
"pro",
|
|
27
|
+
"recall",
|
|
28
|
+
"learn",
|
|
29
|
+
"dashboard",
|
|
26
30
|
"plugin",
|
|
27
31
|
"version",
|
|
28
32
|
"help",
|
|
@@ -48,9 +52,13 @@ export const COMMAND_DESCRIPTIONS: Record<(typeof COMMANDS)[number], string> = {
|
|
|
48
52
|
"install-hooks": "install automatic SessionStart indexing and context hooks",
|
|
49
53
|
"uninstall-hooks": "remove only SessionStart hooks managed by agent-memory",
|
|
50
54
|
completion: "install or print Bash, Zsh, Fish, or PowerShell completion",
|
|
51
|
-
|
|
55
|
+
pro: "install, inspect, or upgrade AgentMemory Pro",
|
|
56
|
+
recall: "recall decisions and context from prior coding sessions with Pro",
|
|
57
|
+
learn: "find repeated corrections worth remembering with Pro",
|
|
58
|
+
dashboard: "open the private local Memory Dashboard",
|
|
59
|
+
plugin: "discover, install, update, or remove optional official plugins",
|
|
52
60
|
version: "print the installed agent-memory version",
|
|
53
|
-
help: "show
|
|
61
|
+
help: "show this command overview",
|
|
54
62
|
};
|
|
55
63
|
|
|
56
64
|
export const PLUGIN_COMMAND_DESCRIPTIONS: Record<(typeof PLUGIN_COMMANDS)[number], string> = {
|
|
@@ -89,6 +97,10 @@ export const COMMAND_OPTIONS: Record<string, readonly string[]> = {
|
|
|
89
97
|
"install-hooks": ["--yes", "--all", "--only"],
|
|
90
98
|
"uninstall-hooks": ["--only"],
|
|
91
99
|
completion: ["--stdout"],
|
|
100
|
+
pro: [],
|
|
101
|
+
recall: ["--scope", "--cwd", "--limit", "--context"],
|
|
102
|
+
learn: [],
|
|
103
|
+
dashboard: ["--no-browser"],
|
|
92
104
|
version: [],
|
|
93
105
|
help: [],
|
|
94
106
|
};
|
package/src/cli.ts
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
import { spawn } from "node:child_process";
|
|
26
26
|
import * as fs from "node:fs";
|
|
27
27
|
|
|
28
|
+
import { COMMAND_DESCRIPTIONS, COMMANDS } from "./cli-spec.js";
|
|
28
29
|
import { type CompletionShell, detectCompletionShell, generateCompletion, installCompletion } from "./completions.js";
|
|
29
30
|
|
|
30
31
|
import {
|
|
@@ -73,6 +74,7 @@ import {
|
|
|
73
74
|
PluginBootstrapFailure,
|
|
74
75
|
type PluginBootstrapResultV1,
|
|
75
76
|
} from "./plugin-bootstrap.js";
|
|
77
|
+
import type { PluginContextSectionV1 } from "./plugin-host.js";
|
|
76
78
|
import { InstalledPluginRuntimeV1 } from "./plugin-runtime.js";
|
|
77
79
|
|
|
78
80
|
declare const __VERSION__: string;
|
|
@@ -186,21 +188,23 @@ function openExternalUrl(url: string): boolean {
|
|
|
186
188
|
|
|
187
189
|
function printProOverview(installed: boolean): void {
|
|
188
190
|
console.log("");
|
|
189
|
-
console.log("
|
|
190
|
-
console.log(" Session Intelligence Recall decisions and context across Pi, Codex, and Claude Code sessions.");
|
|
191
|
-
console.log(" Guided Learning Turn repeated corrections into reviewable, reversible memory.");
|
|
192
|
-
console.log(" Local Web Console Inspect memories, activity, health, and settings in your browser.");
|
|
191
|
+
console.log("Core remembers what you save. Pro learns from what you do.");
|
|
193
192
|
console.log("");
|
|
194
|
-
console.log("
|
|
193
|
+
console.log("AgentMemory Pro:");
|
|
194
|
+
console.log(" Recall coding history Find decisions and context across Pi, Codex, and Claude Code sessions.");
|
|
195
|
+
console.log(" Learn from corrections Turn repeated fixes into reviewable, reversible memory.");
|
|
196
|
+
console.log(" See and control learning Inspect what AgentMemory remembers and why in the Memory Dashboard.");
|
|
197
|
+
console.log("");
|
|
198
|
+
console.log("No account is required for the free preview. Your coding history stays on this device.");
|
|
195
199
|
console.log("");
|
|
196
200
|
if (installed) {
|
|
197
201
|
console.log("Try it:");
|
|
198
202
|
console.log(' agent-memory recall "what did we decide about authentication?"');
|
|
199
203
|
console.log(" agent-memory learn");
|
|
200
|
-
console.log(" agent-memory
|
|
204
|
+
console.log(" agent-memory dashboard");
|
|
201
205
|
} else {
|
|
202
|
-
console.log("Start your Pro
|
|
203
|
-
console.log(" agent-memory
|
|
206
|
+
console.log("Start your free Pro preview:");
|
|
207
|
+
console.log(" agent-memory pro install");
|
|
204
208
|
}
|
|
205
209
|
}
|
|
206
210
|
|
|
@@ -241,12 +245,10 @@ function printPluginResult(result: PluginBootstrapResultV1, json: boolean, allow
|
|
|
241
245
|
break;
|
|
242
246
|
case "not_installed":
|
|
243
247
|
console.log("AgentMemory Pro is not installed.");
|
|
244
|
-
console.log("Run: agent-memory
|
|
248
|
+
console.log("Run: agent-memory pro install");
|
|
245
249
|
break;
|
|
246
250
|
case "auth_required":
|
|
247
|
-
console.log(
|
|
248
|
-
"Run this command in an interactive terminal to enter an email and activate free daily access.",
|
|
249
|
-
);
|
|
251
|
+
console.log("Run agent-memory pro install to activate the free preview.");
|
|
250
252
|
break;
|
|
251
253
|
case "renewal_required":
|
|
252
254
|
console.log("Renew AgentMemory Pro to continue using paid capabilities.");
|
|
@@ -280,10 +282,23 @@ async function cmdContext(flags: Record<string, string | boolean>) {
|
|
|
280
282
|
ensureDirs();
|
|
281
283
|
if (!noSearch && query) await ensureQmdAvailableForSync();
|
|
282
284
|
const searchResults = noSearch ? "" : await searchRelevantMemories(query);
|
|
283
|
-
const
|
|
285
|
+
const coreContext = buildMemoryContext(searchResults);
|
|
286
|
+
let pluginSections: PluginContextSectionV1[] = [];
|
|
287
|
+
try {
|
|
288
|
+
pluginSections = await new InstalledPluginRuntimeV1({ coreVersion: VERSION }).provideContext({
|
|
289
|
+
host: "agent-memory-cli",
|
|
290
|
+
cwd: process.cwd(),
|
|
291
|
+
query: query || undefined,
|
|
292
|
+
signal: new AbortController().signal,
|
|
293
|
+
});
|
|
294
|
+
} catch {
|
|
295
|
+
// Optional Pro context must never make public-core context unavailable.
|
|
296
|
+
}
|
|
297
|
+
const pluginContext = pluginSections.map((section) => `${section.label}\n\n${section.content}`).join("\n\n");
|
|
298
|
+
const context = [coreContext, pluginContext].filter(Boolean).join("\n\n");
|
|
284
299
|
|
|
285
300
|
if (json) {
|
|
286
|
-
output({ context, directory: getMemoryDir() }, true);
|
|
301
|
+
output({ context, directory: getMemoryDir(), ...(pluginSections.length ? { pluginSections } : {}) }, true);
|
|
287
302
|
} else {
|
|
288
303
|
if (context) {
|
|
289
304
|
process.stdout.write(context);
|
|
@@ -811,8 +826,8 @@ async function cmdInit(flags: Record<string, string | boolean>) {
|
|
|
811
826
|
const plugin = await createDefaultPluginBootstrap(VERSION).list();
|
|
812
827
|
if (plugin.result === "not_installed") {
|
|
813
828
|
console.log("");
|
|
814
|
-
console.log("Optional:
|
|
815
|
-
console.log("
|
|
829
|
+
console.log("Optional: Pro recalls coding history and learns from repeated corrections.");
|
|
830
|
+
console.log("Try it without an account: agent-memory pro install");
|
|
816
831
|
}
|
|
817
832
|
} catch {
|
|
818
833
|
// Commercial discovery must never make core initialization fail.
|
|
@@ -957,8 +972,8 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
957
972
|
}
|
|
958
973
|
if (!officialPlugin.installed) {
|
|
959
974
|
console.log("");
|
|
960
|
-
console.log("
|
|
961
|
-
console.log("
|
|
975
|
+
console.log("AgentMemory Pro: not installed");
|
|
976
|
+
console.log(" try without an account: agent-memory pro install");
|
|
962
977
|
}
|
|
963
978
|
}
|
|
964
979
|
}
|
|
@@ -1001,9 +1016,10 @@ Usage:
|
|
|
1001
1016
|
agent-memory plugin uninstall --yes
|
|
1002
1017
|
agent-memory plugin manage [--no-browser]
|
|
1003
1018
|
|
|
1004
|
-
The public core remains fully usable without AgentMemory Pro.
|
|
1005
|
-
|
|
1006
|
-
|
|
1019
|
+
The public core remains fully usable without AgentMemory Pro. Install uses a random
|
|
1020
|
+
installation identifier and requires no account or email. The free preview includes
|
|
1021
|
+
10 recalls and one learning scan per local day; indexing and the Memory Dashboard
|
|
1022
|
+
remain available. Memory and session content stay on this device.`);
|
|
1007
1023
|
}
|
|
1008
1024
|
|
|
1009
1025
|
function pluginCommandFailure(command: string, error: unknown): PluginBootstrapResultV1 {
|
|
@@ -1028,24 +1044,24 @@ function pluginCommandFailure(command: string, error: unknown): PluginBootstrapR
|
|
|
1028
1044
|
};
|
|
1029
1045
|
}
|
|
1030
1046
|
|
|
1031
|
-
async function cmdPlugin(
|
|
1047
|
+
async function cmdPlugin(
|
|
1048
|
+
flags: Record<string, string | boolean>,
|
|
1049
|
+
positional: string[],
|
|
1050
|
+
): Promise<PluginBootstrapResultV1 | null> {
|
|
1032
1051
|
const json = hasFlag(flags, "json");
|
|
1033
1052
|
const subcommand = positional[0] ?? "list";
|
|
1034
1053
|
if (subcommand === "help" || hasFlag(flags, "help")) {
|
|
1035
1054
|
printPluginUsage();
|
|
1036
|
-
return;
|
|
1055
|
+
return null;
|
|
1037
1056
|
}
|
|
1038
1057
|
const channel = getFlag(flags, "channel") ?? "stable";
|
|
1039
1058
|
if (channel !== "stable") {
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
new PluginBootstrapFailure("channel_invalid", "--channel supports only 'stable'"),
|
|
1044
|
-
),
|
|
1045
|
-
json,
|
|
1046
|
-
false,
|
|
1059
|
+
const failure = pluginCommandFailure(
|
|
1060
|
+
subcommand,
|
|
1061
|
+
new PluginBootstrapFailure("channel_invalid", "--channel supports only 'stable'"),
|
|
1047
1062
|
);
|
|
1048
|
-
|
|
1063
|
+
printPluginResult(failure, json, false);
|
|
1064
|
+
return failure;
|
|
1049
1065
|
}
|
|
1050
1066
|
const allowBrowser = !json && !hasFlag(flags, "no-browser") && Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
1051
1067
|
const manager = createDefaultPluginBootstrap(VERSION);
|
|
@@ -1098,6 +1114,55 @@ async function cmdPlugin(flags: Record<string, string | boolean>, positional: st
|
|
|
1098
1114
|
result = pluginCommandFailure(subcommand, error);
|
|
1099
1115
|
}
|
|
1100
1116
|
printPluginResult(result, json, allowBrowser && (subcommand === "install" || subcommand === "manage"));
|
|
1117
|
+
return result;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
async function printFirstRunProof(): Promise<void> {
|
|
1121
|
+
try {
|
|
1122
|
+
const result = await new InstalledPluginRuntimeV1({ coreVersion: VERSION }).run("index", {
|
|
1123
|
+
args: [],
|
|
1124
|
+
flags: {},
|
|
1125
|
+
signal: new AbortController().signal,
|
|
1126
|
+
});
|
|
1127
|
+
if (!result?.ok || !result.data || typeof result.data !== "object") return;
|
|
1128
|
+
const stats = (result.data as { stats?: { discovered?: Record<string, number>; selected?: number } }).stats;
|
|
1129
|
+
if (!stats?.discovered) return;
|
|
1130
|
+
const hosts = [
|
|
1131
|
+
["Claude Code", stats.discovered.claude ?? 0],
|
|
1132
|
+
["Codex", stats.discovered.codex ?? 0],
|
|
1133
|
+
["Pi", stats.discovered.pi ?? 0],
|
|
1134
|
+
] as const;
|
|
1135
|
+
console.log("");
|
|
1136
|
+
console.log("Found local coding history:");
|
|
1137
|
+
for (const [label, count] of hosts) console.log(` ${label.padEnd(13)} ${count} sessions`);
|
|
1138
|
+
console.log("");
|
|
1139
|
+
console.log(`${stats.selected ?? 0} sessions available for local recall. Nothing was uploaded.`);
|
|
1140
|
+
console.log("");
|
|
1141
|
+
console.log('Try: agent-memory recall "what did we decide about authentication?"');
|
|
1142
|
+
console.log("Open: agent-memory dashboard");
|
|
1143
|
+
} catch {
|
|
1144
|
+
// Personalized proof is helpful but must never turn a successful install into a failure.
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
async function cmdPro(flags: Record<string, string | boolean>, positional: string[]): Promise<void> {
|
|
1149
|
+
const subcommand = positional[0];
|
|
1150
|
+
if (!subcommand) {
|
|
1151
|
+
await cmdPlugin(flags, ["list"]);
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
const mapped = subcommand === "upgrade" ? "update" : subcommand;
|
|
1155
|
+
if (!["install", "status", "update", "manage"].includes(mapped)) {
|
|
1156
|
+
const json = hasFlag(flags, "json");
|
|
1157
|
+
const message = `Unknown Pro command: ${subcommand}. Available commands: install, status, upgrade, manage.`;
|
|
1158
|
+
if (json) console.log(JSON.stringify({ error: message }));
|
|
1159
|
+
else console.error(`Error: ${message}`);
|
|
1160
|
+
process.exitCode = 1;
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
const result = await cmdPlugin(flags, [mapped]);
|
|
1164
|
+
if (!hasFlag(flags, "json") && mapped === "install" && ["installed", "upgraded"].includes(result?.result ?? ""))
|
|
1165
|
+
await printFirstRunProof();
|
|
1101
1166
|
}
|
|
1102
1167
|
|
|
1103
1168
|
// ---------------------------------------------------------------------------
|
|
@@ -1105,28 +1170,18 @@ async function cmdPlugin(flags: Record<string, string | boolean>, positional: st
|
|
|
1105
1170
|
// ---------------------------------------------------------------------------
|
|
1106
1171
|
|
|
1107
1172
|
function printUsage() {
|
|
1173
|
+
const commandWidth = Math.max(...COMMANDS.map((command) => command.length));
|
|
1174
|
+
const commandList = COMMANDS.map(
|
|
1175
|
+
(command) => ` ${command.padEnd(commandWidth)} ${COMMAND_DESCRIPTIONS[command]}`,
|
|
1176
|
+
).join("\n");
|
|
1177
|
+
|
|
1108
1178
|
console.log(`agent-memory — persistent memory for coding agents
|
|
1109
1179
|
|
|
1110
1180
|
Usage:
|
|
1111
1181
|
agent-memory <command> [options]
|
|
1112
1182
|
|
|
1113
1183
|
Commands:
|
|
1114
|
-
|
|
1115
|
-
install-skills Install (or --uninstall) bundled skills
|
|
1116
|
-
uninstall-skills Uninstall bundled skills
|
|
1117
|
-
context Build context; optionally retrieve memories with --query
|
|
1118
|
-
write Write to memory files (default: daily; optional --source-uri)
|
|
1119
|
-
read Read memory files
|
|
1120
|
-
scratchpad Manage checklist items
|
|
1121
|
-
search Search across memory files (requires qmd)
|
|
1122
|
-
distil Generate compact MEMORY.md index from daily logs + topics
|
|
1123
|
-
sync Re-index and embed all files (requires qmd)
|
|
1124
|
-
init Initialize memory directory and qmd collection
|
|
1125
|
-
status Show configuration and status (--probe for a live embeddings check)
|
|
1126
|
-
completion Install or print shell completion
|
|
1127
|
-
install-hooks Install managed SessionStart hooks
|
|
1128
|
-
uninstall-hooks Remove only managed SessionStart hooks
|
|
1129
|
-
plugin Discover, install, update, or remove optional official plugins
|
|
1184
|
+
${commandList}
|
|
1130
1185
|
|
|
1131
1186
|
Global flags:
|
|
1132
1187
|
--dir <path> Override memory directory
|
|
@@ -1152,8 +1207,10 @@ Examples:
|
|
|
1152
1207
|
agent-memory status --json
|
|
1153
1208
|
agent-memory completion zsh
|
|
1154
1209
|
agent-memory install-hooks --yes
|
|
1155
|
-
agent-memory
|
|
1156
|
-
agent-memory
|
|
1210
|
+
agent-memory pro status
|
|
1211
|
+
agent-memory pro install
|
|
1212
|
+
agent-memory recall "what did we decide about authentication?"
|
|
1213
|
+
agent-memory dashboard`);
|
|
1157
1214
|
}
|
|
1158
1215
|
|
|
1159
1216
|
// ---------------------------------------------------------------------------
|
|
@@ -1245,18 +1302,22 @@ async function main() {
|
|
|
1245
1302
|
case "plugin":
|
|
1246
1303
|
await cmdPlugin(flags, positional);
|
|
1247
1304
|
break;
|
|
1305
|
+
case "pro":
|
|
1306
|
+
await cmdPro(flags, positional);
|
|
1307
|
+
break;
|
|
1248
1308
|
default: {
|
|
1249
1309
|
const controller = new AbortController();
|
|
1250
1310
|
const abort = () => controller.abort();
|
|
1251
1311
|
process.once("SIGINT", abort);
|
|
1252
1312
|
try {
|
|
1253
|
-
const
|
|
1313
|
+
const pluginCommand = command === "dashboard" ? "web" : command;
|
|
1314
|
+
const result = await new InstalledPluginRuntimeV1({ coreVersion: VERSION }).run(pluginCommand, {
|
|
1254
1315
|
args: positional,
|
|
1255
1316
|
flags,
|
|
1256
1317
|
signal: controller.signal,
|
|
1257
1318
|
});
|
|
1258
1319
|
if (!result) exitError(`Unknown command: ${command}. Run 'agent-memory help' for usage.`, json);
|
|
1259
|
-
if (!result.ok) exitError(result.error?.message ?? `Plugin command ${
|
|
1320
|
+
if (!result.ok) exitError(result.error?.message ?? `Plugin command ${pluginCommand} failed`, json);
|
|
1260
1321
|
output(result.data ?? { ok: true }, json);
|
|
1261
1322
|
} finally {
|
|
1262
1323
|
process.removeListener("SIGINT", abort);
|
package/src/plugin-bootstrap.ts
CHANGED
|
@@ -195,8 +195,8 @@ const MISSING_ENTITLEMENT: PluginEntitlementStatusV1 = {
|
|
|
195
195
|
};
|
|
196
196
|
|
|
197
197
|
const OFFICIAL_PLUGINS = [
|
|
198
|
-
{ id: OFFICIAL_PLUGIN_IDS[0], name: "
|
|
199
|
-
{ id: OFFICIAL_PLUGIN_IDS[1], name: "
|
|
198
|
+
{ id: OFFICIAL_PLUGIN_IDS[0], name: "Coding History Recall" },
|
|
199
|
+
{ id: OFFICIAL_PLUGIN_IDS[1], name: "Memory Dashboard" },
|
|
200
200
|
] as const;
|
|
201
201
|
|
|
202
202
|
const PACKAGE_MAX_BYTES = 64 * 1024 * 1024;
|