myagentmemory 0.4.13 → 0.4.15
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 +48 -24
- package/dist/cli-spec.d.ts +25 -0
- package/dist/cli-spec.js +211 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +387 -4
- package/dist/completions.d.ts +13 -0
- package/dist/completions.js +429 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +17 -12
- package/dist/hooks.d.ts +42 -0
- package/dist/hooks.js +444 -0
- package/dist/plugin-bootstrap.d.ts +202 -0
- package/dist/plugin-bootstrap.js +628 -0
- package/dist/plugin-host.d.ts +136 -0
- package/dist/plugin-host.js +98 -0
- package/dist/plugin-runtime.d.ts +22 -0
- package/dist/plugin-runtime.js +238 -0
- package/dist/plugin-service.d.ts +49 -0
- package/dist/plugin-service.js +457 -0
- package/docs/official-plugin-bootstrap.md +337 -0
- package/package.json +35 -2
- package/src/cli-spec.ts +236 -0
- package/src/cli.ts +404 -4
- package/src/completions.ts +501 -0
- package/src/core.ts +17 -12
- package/src/hooks.ts +485 -0
- package/src/plugin-bootstrap.ts +944 -0
- package/src/plugin-host.ts +255 -0
- package/src/plugin-runtime.ts +326 -0
- package/src/plugin-service.ts +537 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# Official plugin bootstrap and host contract
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted design on 2026-08-16 and revised on 2026-08-17. The public core implements host types, loopback email 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 plan grants a configurable number of agent sessions per normalized email and UTC day; durable account authentication, payment, renewal, and account management remain deferred.
|
|
6
|
+
|
|
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
|
+
|
|
9
|
+
## Decision
|
|
10
|
+
|
|
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
|
+
|
|
13
|
+
The primary user command is:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
agent-memory plugin install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`plugin install` is an idempotent reconcile operation:
|
|
20
|
+
|
|
21
|
+
| Local state | Entitlement state | Result |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| Plugin absent | Active or grace | Install the compatible signed bundle |
|
|
24
|
+
| Plugin older than the selected release | Active or grace | Upgrade atomically |
|
|
25
|
+
| Plugin current | Active or grace | Report that it is current |
|
|
26
|
+
| Any | Missing | Start loopback email activation in an interactive terminal |
|
|
27
|
+
| Any | Expired | Direct the user to renewal; leave core available |
|
|
28
|
+
| Incompatible bundle | Any | Leave the current version untouched and explain the required core version |
|
|
29
|
+
|
|
30
|
+
An absent plugin cannot activate itself. The public bootstrap collects an email locally, obtains a server-issued usage credential and short-lived artifact grant, and verifies the release and artifact. The credential is persisted only after the service accepts activation. After installation, the public host reconstructs the free account-metered capability policy in core code and checks required capabilities before commands and hooks. Signed long-lived entitlements can extend this credential when authentication and payment ship.
|
|
31
|
+
|
|
32
|
+
## Ownership boundary
|
|
33
|
+
|
|
34
|
+
The public core owns:
|
|
35
|
+
|
|
36
|
+
- CLI discovery and bootstrap commands;
|
|
37
|
+
- an allowlisted control-plane client;
|
|
38
|
+
- credential-store and signed-entitlement persistence abstractions;
|
|
39
|
+
- signed catalog and artifact verification;
|
|
40
|
+
- transactional install, upgrade, rollback, and uninstall;
|
|
41
|
+
- a versioned, permission-checked plugin host API;
|
|
42
|
+
- command dispatch to an activated official bundle;
|
|
43
|
+
- helpful unavailable-command messages when an official capability is absent.
|
|
44
|
+
|
|
45
|
+
The commercial distribution owns:
|
|
46
|
+
|
|
47
|
+
- the proprietary plugin runtime and implementations;
|
|
48
|
+
- Session Intelligence and Web Console assets;
|
|
49
|
+
- entitlement interpretation beyond the public signed-claim format;
|
|
50
|
+
- paid command, hook, worker, and web-server behavior;
|
|
51
|
+
- the authenticated website, billing integration, entitlement ledger, and artifact service;
|
|
52
|
+
- signed release production and commercial notices.
|
|
53
|
+
|
|
54
|
+
Core memory operations must continue to work when the service is unreachable, a plugin is absent, an entitlement expires, or an upgrade fails.
|
|
55
|
+
|
|
56
|
+
## Alternatives rejected for v1
|
|
57
|
+
|
|
58
|
+
- **Put the bootstrap inside the commercial plugin:** impossible when the plugin is not installed and unable to repair a broken installation.
|
|
59
|
+
- **Ship a separate permanent Pro CLI:** duplicates command parsing and core behavior and makes it unclear which `agent-memory` binary owns user data.
|
|
60
|
+
- **Bundle paid code in the public package behind an entitlement flag:** exposes the paid implementation under the public artifact and license boundary.
|
|
61
|
+
- **Open a checkout page from npm/Homebrew postinstall:** unreliable in non-interactive environments and surprising for users who requested only the core.
|
|
62
|
+
- **Use a general remote marketplace immediately:** expands code-loading, sandbox, trust, dependency, and moderation scope before the first-party boundary is proven.
|
|
63
|
+
- **Pass license keys as CLI arguments or environment values:** exposes reusable credentials through shell history, process inspection, CI logs, or inherited environments.
|
|
64
|
+
|
|
65
|
+
## CLI contract
|
|
66
|
+
|
|
67
|
+
### Bootstrap commands
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
agent-memory plugin
|
|
71
|
+
agent-memory plugin list
|
|
72
|
+
agent-memory plugin status
|
|
73
|
+
agent-memory plugin install [--channel stable] [--no-browser] [--yes]
|
|
74
|
+
agent-memory plugin update [--channel stable]
|
|
75
|
+
agent-memory plugin uninstall [--yes]
|
|
76
|
+
agent-memory plugin manage [--no-browser]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- `plugin` with no subcommand prints a discovery summary and the next relevant command.
|
|
80
|
+
- `list` reports known official plugins and whether each is installed and available. It does not download artifacts or inspect memory.
|
|
81
|
+
- `status` is read-only. It reports the installed bundle, selected channel, compatibility, entitlement state, and update availability.
|
|
82
|
+
- `install` authenticates when necessary, then installs, upgrades, or reports current state.
|
|
83
|
+
- `update` requires an existing installation and never starts a new purchase implicitly.
|
|
84
|
+
- `uninstall` removes executable plugin material and the active receipt. It preserves core memory, plugin state, and the permission-restricted activation credential.
|
|
85
|
+
- `manage` remains unavailable until authenticated account and billing management exists.
|
|
86
|
+
|
|
87
|
+
Installed plugins contribute top-level commands such as `recall`, `learn`, `worker`, and `web`. Bootstrap command names are reserved by the core and cannot be replaced by a plugin.
|
|
88
|
+
|
|
89
|
+
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
|
+
|
|
91
|
+
### Discovery behavior
|
|
92
|
+
|
|
93
|
+
After a successful interactive `agent-memory init`, the core may print one informational line:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
Optional: AgentMemory Pro adds session recall and a local Web Console.
|
|
97
|
+
Run: agent-memory plugin install
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Top-level help includes an `Optional official plugins` section. Human-readable `status` may include the same recommendation while no official plugin is installed. Routine `context`, `read`, `write`, `search`, and scratchpad commands never show commercial prompts.
|
|
101
|
+
|
|
102
|
+
The core must not open a browser during package installation, `init`, `help`, `status`, or any normal memory operation. A browser may open only after an explicit interactive `plugin install`. `--no-browser`, non-interactive execution, and `--json` fail closed with `auth_required` when no activation record exists.
|
|
103
|
+
|
|
104
|
+
### Machine-readable output
|
|
105
|
+
|
|
106
|
+
Every bootstrap command supports `--json` and emits one JSON document with a versioned envelope:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"schemaVersion": 1,
|
|
111
|
+
"command": "plugin.install",
|
|
112
|
+
"ok": true,
|
|
113
|
+
"result": "installed",
|
|
114
|
+
"bundle": {
|
|
115
|
+
"id": "agentmemory.pro",
|
|
116
|
+
"previousVersion": null,
|
|
117
|
+
"version": "1.0.0",
|
|
118
|
+
"channel": "stable"
|
|
119
|
+
},
|
|
120
|
+
"entitlement": {
|
|
121
|
+
"plan": "pro",
|
|
122
|
+
"state": "active",
|
|
123
|
+
"capabilities": {
|
|
124
|
+
"learning": { "enabled": true },
|
|
125
|
+
"web-console": { "enabled": true }
|
|
126
|
+
},
|
|
127
|
+
"expiresAt": "2027-08-16T00:00:00Z",
|
|
128
|
+
"offlineUntil": "2026-09-15T00:00:00Z"
|
|
129
|
+
},
|
|
130
|
+
"nextAction": null
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`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
|
+
|
|
136
|
+
## Free activation flow
|
|
137
|
+
|
|
138
|
+
1. `agent-memory plugin install` starts an HTTP server bound to `127.0.0.1` on an ephemeral port.
|
|
139
|
+
2. The CLI prints and opens a nonce-bearing local URL. The page accepts one email address with bounded input, an exact Host and nonce path, same-origin browser request validation, restrictive response headers, and a five-minute deadline.
|
|
140
|
+
3. Submission returns a completion page but does not create a local credential yet.
|
|
141
|
+
4. The waiting CLI sends the email plus core, installed-bundle, platform, architecture, release-channel, and consent-version fields to the private control plane. Its activation database stores none of the user's memory, session content, queries, repository paths, raw agent session identifiers, IP address, or user-agent string.
|
|
142
|
+
5. The service normalizes the email, stores only a hash of a random usage credential, and returns the credential, a free account-metered entitlement, and a short-lived object-bound artifact grant. Only then does the CLI atomically write a mode-0600 activation record.
|
|
143
|
+
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. Each paid SessionStart hook reserves one opaque operation against the email's UTC-day allowance, commits after useful hook work, and releases on failure. Exhaustion skips paid hook work without affecting public-core context.
|
|
145
|
+
|
|
146
|
+
Email ownership is not verified in this free flow. Authentication, payment, renewal, account management, and signed paid entitlements are not implemented yet.
|
|
147
|
+
|
|
148
|
+
## Future authentication and purchase flow
|
|
149
|
+
|
|
150
|
+
1. The bootstrap inspects the local install receipt and signed entitlement without loading plugin code.
|
|
151
|
+
2. If no usable entitlement or account credential exists, it requests a short-lived device authorization.
|
|
152
|
+
3. The CLI prints a verification URL and user code and, for an interactive request, attempts to open the URL.
|
|
153
|
+
4. The website authenticates the user and offers AgentMemory Pro or an Enterprise contact/organization path.
|
|
154
|
+
5. Successful payment or organization assignment updates the server-side entitlement ledger.
|
|
155
|
+
6. The CLI polls within the server-provided interval and deadline. On success, it receives a signed entitlement and a short-lived artifact grant.
|
|
156
|
+
7. Installation continues in the same command without asking the user to copy a license key.
|
|
157
|
+
|
|
158
|
+
Canceling, timing out, or failing payment leaves the machine unchanged. Authentication credentials are never accepted through command-line arguments. The first release should use an operating-system credential store when available and an explicit, permission-restricted fallback when it is not. Credential persistence and fallback behavior must be disclosed before launch.
|
|
159
|
+
|
|
160
|
+
An Enterprise administrator may pre-provision an organization entitlement or managed installation policy. Enterprise automation must accept a license-file path or managed credential reference, not a raw secret on the command line.
|
|
161
|
+
|
|
162
|
+
## Control-plane boundary
|
|
163
|
+
|
|
164
|
+
The service exposes:
|
|
165
|
+
|
|
166
|
+
- `POST /v1/plugin/access` for a free account-metered entitlement, a usage credential, and a short-lived artifact grant;
|
|
167
|
+
- `POST /v1/plugin/sessions/reserve|commit|release` for atomic daily allowance enforcement;
|
|
168
|
+
- `GET /v1/plugin/releases` for an Ed25519-signed release selected from the private R2 catalog;
|
|
169
|
+
- `GET|HEAD /v1/artifacts/download` for the exact content-addressed object authorized by the bearer grant.
|
|
170
|
+
|
|
171
|
+
The access request contains the submitted email plus the bounded core, bundle, platform, architecture, release-channel, and consent-version fields described above. Session metering sends only a random operation ID and bearer credential; D1 associates those values with a normalized email and UTC-day counter. Application payloads contain no 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
|
+
|
|
173
|
+
- create and poll a device authorization;
|
|
174
|
+
- read the authenticated principal's effective entitlement;
|
|
175
|
+
- fetch a signed release catalog;
|
|
176
|
+
- mint a short-lived artifact download grant;
|
|
177
|
+
- return the account-management URL;
|
|
178
|
+
- support Enterprise organization assignment without consumer checkout.
|
|
179
|
+
|
|
180
|
+
The bootstrap may send only:
|
|
181
|
+
|
|
182
|
+
- a random installation identifier;
|
|
183
|
+
- core version, plugin-host API version, platform, and architecture;
|
|
184
|
+
- requested bundle ID, installed bundle version, and release channel;
|
|
185
|
+
- a pseudonymous license or organization identifier;
|
|
186
|
+
- protocol nonces, opaque quota operation IDs, and authentication material required for the request.
|
|
187
|
+
|
|
188
|
+
It must never send memory contents, search queries, session contents, raw agent session identifiers, working-directory names, repository names, filesystem paths, or qmd data. The bounded allowance counter is authorization state, not general product telemetry.
|
|
189
|
+
|
|
190
|
+
Production builds use an allowlisted HTTPS origin. Development endpoint overrides must be explicit, must not silently affect production builds, and must never weaken TLS verification.
|
|
191
|
+
|
|
192
|
+
## Signed entitlement contract
|
|
193
|
+
|
|
194
|
+
The server issues a signed, versioned entitlement containing the minimum claims needed for offline activation:
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"schemaVersion": 1,
|
|
199
|
+
"licenseId": "lic_pseudonymous_id",
|
|
200
|
+
"plan": "pro",
|
|
201
|
+
"features": ["session-intelligence", "web-console"],
|
|
202
|
+
"capabilities": {
|
|
203
|
+
"learning": { "enabled": true },
|
|
204
|
+
"web-console": { "enabled": true }
|
|
205
|
+
},
|
|
206
|
+
"channel": "stable",
|
|
207
|
+
"issuedAt": "2026-08-16T00:00:00Z",
|
|
208
|
+
"refreshAfter": "2026-08-23T00:00:00Z",
|
|
209
|
+
"expiresAt": "2027-08-16T00:00:00Z",
|
|
210
|
+
"offlineUntil": "2026-09-15T00:00:00Z"
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
It contains no name, email address, billing details, memory identifier, or filesystem information. Plan identifiers (`free`, `trial`, `pro`, `team`, or `enterprise`) are commercial policy; `active`, `grace`, `missing`, and `expired` are separate locally derived verification states and are never inferred from the plan name. Enterprise may satisfy all `pro` capability requirements while adding organization-scoped policy claims.
|
|
215
|
+
|
|
216
|
+
Capabilities authorize individual commands, hooks, workers, and local API routes. A capability may carry a positive device-local daily quota. The signed policy configures the limit, while usage remains in a crash-safe local ledger; quota accounting does not add product telemetry to the bootstrap protocol. A plan never implicitly enables a capability, and an active entitlement with a disabled or absent capability fails closed for that operation.
|
|
217
|
+
|
|
218
|
+
The exact signed-envelope format, key custody, rotation procedure, and grace duration remain launch decisions. Verification keys are pinned by the public core, support overlap during rotation, and never come from the downloaded artifact being verified.
|
|
219
|
+
|
|
220
|
+
## Release catalog and artifact contract
|
|
221
|
+
|
|
222
|
+
The signed catalog selects an artifact by bundle ID, channel, core compatibility, plugin-host API compatibility, platform, and architecture. Each release describes at least:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"schemaVersion": 1,
|
|
227
|
+
"id": "agentmemory.pro",
|
|
228
|
+
"version": "1.0.0",
|
|
229
|
+
"channel": "stable",
|
|
230
|
+
"core": ">=0.5.0 <1.0.0",
|
|
231
|
+
"pluginApi": 1,
|
|
232
|
+
"platform": "any",
|
|
233
|
+
"architecture": "any",
|
|
234
|
+
"sha256": "hex-encoded archive digest",
|
|
235
|
+
"size": 123456,
|
|
236
|
+
"entrypoint": "bundle/index.js",
|
|
237
|
+
"plugins": ["agentmemory.session-intelligence", "agentmemory.web-console"]
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
The archive contains compiled commercial code, plugin manifests, contributed skills, commercial license text, preserved public-core notices, and third-party notices. It must not depend on npm lifecycle scripts, download dependencies during activation, or include real credentials. Archive paths, symlinks, expanded size, file count, and permissions are validated before extraction.
|
|
242
|
+
|
|
243
|
+
## Transactional installation
|
|
244
|
+
|
|
245
|
+
The machine-wide user installation is independent of `AGENT_MEMORY_DIR`, which selects a memory store. The default install root is `~/.agent-memory/system/plugins`; the dedicated non-secret `AGENT_MEMORY_PLUGIN_DIR` setting may override it for managed deployment and tests.
|
|
246
|
+
|
|
247
|
+
An install or upgrade must:
|
|
248
|
+
|
|
249
|
+
1. acquire a bounded installation lock;
|
|
250
|
+
2. inspect the current receipt without executing plugin code;
|
|
251
|
+
3. authenticate and resolve a compatible signed catalog entry;
|
|
252
|
+
4. download to a newly created staging directory;
|
|
253
|
+
5. verify catalog signature, artifact digest, archive limits, manifest, and compatibility;
|
|
254
|
+
6. extract without path traversal or link traversal;
|
|
255
|
+
7. load only the declared entry point for a bounded health check;
|
|
256
|
+
8. atomically switch the active-version receipt;
|
|
257
|
+
9. install declared skills and hooks only after successful activation;
|
|
258
|
+
10. preserve the previous known-good version for rollback and remove abandoned staging data.
|
|
259
|
+
|
|
260
|
+
Failure before activation leaves the previous version active. Failure immediately after activation restores the previous receipt. Concurrent installers do not interleave. The core never invokes package-manager lifecycle scripts or elevates privileges.
|
|
261
|
+
|
|
262
|
+
Uninstall removes executable versions, the active receipt, contributed skills, and managed hooks. It does not remove `MEMORY.md`, daily logs, topics, scratchpad items, source session logs, plugin-created review data, or billing state. A separate future purge command would require explicit scope and confirmation.
|
|
263
|
+
|
|
264
|
+
## Plugin host API v1
|
|
265
|
+
|
|
266
|
+
The implementation will expose equivalent TypeScript types from the public package. This document is authoritative until those types ship:
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
export interface AgentMemoryPluginBundleV1 {
|
|
270
|
+
apiVersion: 1;
|
|
271
|
+
manifest: AgentMemoryBundleManifestV1;
|
|
272
|
+
plugins: readonly AgentMemoryPluginV1[];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export interface AgentMemoryPluginV1 {
|
|
276
|
+
manifest: AgentMemoryPluginManifestV1;
|
|
277
|
+
activate(host: AgentMemoryPluginHostV1): Promise<void>;
|
|
278
|
+
healthCheck(host: AgentMemoryPluginHostV1): Promise<{ ok: boolean; message?: string }>;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface AgentMemoryPluginHostV1 {
|
|
282
|
+
apiVersion: 1;
|
|
283
|
+
coreVersion: string;
|
|
284
|
+
registerCommand(command: PluginCommandV1): void;
|
|
285
|
+
registerSessionStartHook(hook: PluginSessionStartHookV1): void;
|
|
286
|
+
getStateDirectory(): string;
|
|
287
|
+
getEntitlement(): Promise<PluginEntitlementStatusV1>;
|
|
288
|
+
redactSecrets(value: string): string;
|
|
289
|
+
writeMemory(request: PluginMemoryWriteV1): Promise<PluginMemoryWriteResultV1>;
|
|
290
|
+
correctMemory(request: PluginMemoryCorrectionV1): Promise<PluginMemoryCorrectionResultV1>;
|
|
291
|
+
scheduleSearchRefresh(reason: string): void;
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
The final exported contract must define the referenced request, result, command, hook, manifest, entitlement-status, permission, cancellation, and structured-error types. Commercial manifests are plan-neutral: they declare `entitlement: "commercial"`, their provided capabilities, and the `requiredCapability` for each guarded command or hook. The loader validates every bundled plugin first, then creates a host instance scoped to that plugin's manifest. Host methods enforce its declared permissions. Plugins receive only derived entitlement state, capability grants, quota policy, and time bounds through host APIs, never raw signed claims or commercial credentials.
|
|
296
|
+
|
|
297
|
+
Installed bundles are trusted, signed first-party JavaScript loaded into the AgentMemory process. Manifest permissions constrain host APIs; they are not an operating-system sandbox and do not remove the bundle's ambient Node.js process or filesystem authority. This contract does not approve arbitrary third-party plugin loading. State-directory isolation prevents accidental host-API crossover, not malicious code running in the same process.
|
|
298
|
+
|
|
299
|
+
Activation order is: verify artifact, verify entitlement, validate every manifest, resolve required dependencies, create permission-scoped host adapters, activate plugins, then register commands and hooks. Registered-but-unavailable dependencies do not satisfy `requires`.
|
|
300
|
+
|
|
301
|
+
## Runtime entitlement behavior
|
|
302
|
+
|
|
303
|
+
The core reloads local entitlement state before every commercial command or compatibility alias and checks its exact required capability before dispatch. Plugin-owned hooks, worker starts, Web Console launches, and commercial API routes must perform the same check through `host.getEntitlement()`. A long-running plugin process must recheck through that host API at a bounded interval and respond safely to expiration or capability removal. Browser-session authorization remains separate from commercial entitlement and never contains subscription credentials.
|
|
304
|
+
|
|
305
|
+
When entitlement is in grace, paid capabilities continue locally and status explains when grace ends. When expired or invalid, new paid work fails closed with a renewal action; core memory remains available and no user data is deleted.
|
|
306
|
+
|
|
307
|
+
## Compatibility and updates
|
|
308
|
+
|
|
309
|
+
- Core and bundle versions follow semantic versioning.
|
|
310
|
+
- The integer plugin-host API changes only for incompatible host-contract revisions.
|
|
311
|
+
- A bundle declares both a core range and a host API version.
|
|
312
|
+
- `plugin install` and `plugin update` choose the newest compatible release in the selected channel, not merely the newest release.
|
|
313
|
+
- Updates occur only after an explicit install/update command or a future separately approved policy. No background auto-download is part of v1.
|
|
314
|
+
- A newer incompatible release is reported without replacing the current working version.
|
|
315
|
+
|
|
316
|
+
## Security and release gates
|
|
317
|
+
|
|
318
|
+
Before launch, automated tests must demonstrate:
|
|
319
|
+
|
|
320
|
+
- public `myagentmemory` package contents contain no paid code, SPA assets, private source maps, commercial credentials, or private release configuration;
|
|
321
|
+
- missing, active, grace, expired, malformed, wrong-audience, and wrong-signature entitlements fail as specified;
|
|
322
|
+
- absent, current, outdated, interrupted, corrupt, incompatible, and concurrent installation paths are deterministic and recoverable;
|
|
323
|
+
- archive traversal, symlink traversal, oversized archives, digest mismatch, unknown signing keys, and unauthorized commands fail closed;
|
|
324
|
+
- all paid entry points enforce entitlement while every core memory operation remains available;
|
|
325
|
+
- `--json` remains parseable and secret-free and non-interactive use never opens a browser;
|
|
326
|
+
- install, update, rollback, and uninstall work on supported macOS, Linux, and Windows environments.
|
|
327
|
+
|
|
328
|
+
## Deferred work
|
|
329
|
+
|
|
330
|
+
This contract does not approve:
|
|
331
|
+
|
|
332
|
+
- arbitrary third-party plugin loading or a public marketplace;
|
|
333
|
+
- remote execution of plugin code;
|
|
334
|
+
- silent or package-postinstall browser prompts;
|
|
335
|
+
- background commercial telemetry or transmission of memory data;
|
|
336
|
+
- pricing, seat counts, device limits, or a billing vendor;
|
|
337
|
+
- Enterprise readiness claims before SSO, policy, retention, audit, DLP, and managed deployment are implemented and tested.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myagentmemory",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.15",
|
|
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",
|
|
@@ -8,10 +8,26 @@
|
|
|
8
8
|
".": {
|
|
9
9
|
"types": "./dist/core.d.ts",
|
|
10
10
|
"default": "./dist/core.js"
|
|
11
|
+
},
|
|
12
|
+
"./plugin-bootstrap": {
|
|
13
|
+
"types": "./dist/plugin-bootstrap.d.ts",
|
|
14
|
+
"default": "./dist/plugin-bootstrap.js"
|
|
15
|
+
},
|
|
16
|
+
"./plugin-host": {
|
|
17
|
+
"types": "./dist/plugin-host.d.ts",
|
|
18
|
+
"default": "./dist/plugin-host.js"
|
|
19
|
+
},
|
|
20
|
+
"./completions": {
|
|
21
|
+
"types": "./dist/completions.d.ts",
|
|
22
|
+
"default": "./dist/completions.js"
|
|
23
|
+
},
|
|
24
|
+
"./hooks": {
|
|
25
|
+
"types": "./dist/hooks.d.ts",
|
|
26
|
+
"default": "./dist/hooks.js"
|
|
11
27
|
}
|
|
12
28
|
},
|
|
13
29
|
"bin": {
|
|
14
|
-
"agent-memory": "
|
|
30
|
+
"agent-memory": "dist/cli.js"
|
|
15
31
|
},
|
|
16
32
|
"type": "module",
|
|
17
33
|
"engines": {
|
|
@@ -56,6 +72,21 @@
|
|
|
56
72
|
"dist/cli.js",
|
|
57
73
|
"dist/core.d.ts",
|
|
58
74
|
"dist/core.js",
|
|
75
|
+
"dist/cli-spec.d.ts",
|
|
76
|
+
"dist/cli-spec.js",
|
|
77
|
+
"dist/completions.d.ts",
|
|
78
|
+
"dist/completions.js",
|
|
79
|
+
"dist/hooks.d.ts",
|
|
80
|
+
"dist/hooks.js",
|
|
81
|
+
"dist/plugin-bootstrap.d.ts",
|
|
82
|
+
"dist/plugin-bootstrap.js",
|
|
83
|
+
"dist/plugin-host.d.ts",
|
|
84
|
+
"dist/plugin-host.js",
|
|
85
|
+
"dist/plugin-runtime.d.ts",
|
|
86
|
+
"dist/plugin-runtime.js",
|
|
87
|
+
"dist/plugin-service.d.ts",
|
|
88
|
+
"dist/plugin-service.js",
|
|
89
|
+
"docs/official-plugin-bootstrap.md",
|
|
59
90
|
"README.md",
|
|
60
91
|
"LICENSE"
|
|
61
92
|
],
|
|
@@ -69,6 +100,7 @@
|
|
|
69
100
|
"build:lib": "tsc -p tsconfig.build.json",
|
|
70
101
|
"build:cli": "bun build src/cli.ts --compile --outfile dist/agent-memory --define __VERSION__=\"'$(node -p \"require('./package.json').version\")'\"",
|
|
71
102
|
"eval:feedback": "bun eval/run.ts",
|
|
103
|
+
"prepare": "npm run build:lib",
|
|
72
104
|
"prepack": "npm run build:lib",
|
|
73
105
|
"lint": "biome check .",
|
|
74
106
|
"test": "bun test test/unit.test.ts",
|
|
@@ -85,6 +117,7 @@
|
|
|
85
117
|
"typescript": "^5.9.3"
|
|
86
118
|
},
|
|
87
119
|
"overrides": {
|
|
120
|
+
"esbuild": "^0.28.1",
|
|
88
121
|
"rimraf": "^6.1.3",
|
|
89
122
|
"glob": "^13.0.3"
|
|
90
123
|
}
|
package/src/cli-spec.ts
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
export type CliValueKind = "directory" | "file" | "number" | "value";
|
|
2
|
+
|
|
3
|
+
export interface CliOptionSpec {
|
|
4
|
+
description: string;
|
|
5
|
+
value?: {
|
|
6
|
+
label: string;
|
|
7
|
+
kind: CliValueKind;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const COMMANDS = [
|
|
12
|
+
"context",
|
|
13
|
+
"write",
|
|
14
|
+
"read",
|
|
15
|
+
"scratchpad",
|
|
16
|
+
"search",
|
|
17
|
+
"distil",
|
|
18
|
+
"sync",
|
|
19
|
+
"init",
|
|
20
|
+
"status",
|
|
21
|
+
"install-skills",
|
|
22
|
+
"uninstall-skills",
|
|
23
|
+
"install-hooks",
|
|
24
|
+
"uninstall-hooks",
|
|
25
|
+
"completion",
|
|
26
|
+
"plugin",
|
|
27
|
+
"version",
|
|
28
|
+
"help",
|
|
29
|
+
] as const;
|
|
30
|
+
|
|
31
|
+
export const PLUGIN_COMMANDS = ["list", "status", "install", "update", "uninstall", "manage"] as const;
|
|
32
|
+
|
|
33
|
+
export const WORKER_ACTIONS = [] as const;
|
|
34
|
+
export const SCRATCHPAD_ACTIONS = ["add", "done", "undo", "clear_done", "list"] as const;
|
|
35
|
+
|
|
36
|
+
export const COMMAND_DESCRIPTIONS: Record<(typeof COMMANDS)[number], string> = {
|
|
37
|
+
context: "build context from scratchpad, logs, topics, and long-term memory",
|
|
38
|
+
write: "append or overwrite a daily, topic, or long-term memory entry",
|
|
39
|
+
read: "read daily, topic, scratchpad, or long-term memory",
|
|
40
|
+
scratchpad: "add, complete, reopen, list, or clear persistent checklist items",
|
|
41
|
+
search: "search indexed memory with keyword, semantic, or deep qmd modes",
|
|
42
|
+
distil: "rebuild a compact MEMORY.md index from logs and topics",
|
|
43
|
+
sync: "update the qmd index and semantic embeddings",
|
|
44
|
+
init: "create memory storage and configure qmd when available",
|
|
45
|
+
status: "show memory paths, file counts, qmd, and embedding health",
|
|
46
|
+
"install-skills": "install core instructions for detected agents",
|
|
47
|
+
"uninstall-skills": "remove core instructions from detected agents",
|
|
48
|
+
"install-hooks": "install automatic SessionStart indexing and context hooks",
|
|
49
|
+
"uninstall-hooks": "remove only SessionStart hooks managed by agent-memory",
|
|
50
|
+
completion: "install or print Bash, Zsh, Fish, or PowerShell completion",
|
|
51
|
+
plugin: "index, recall, learn from, and evaluate prior agent sessions",
|
|
52
|
+
version: "print the installed agent-memory version",
|
|
53
|
+
help: "show top-level, command, or nested plugin help",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const PLUGIN_COMMAND_DESCRIPTIONS: Record<(typeof PLUGIN_COMMANDS)[number], string> = {
|
|
57
|
+
list: "list optional official plugins and local availability",
|
|
58
|
+
status: "show the installed bundle and entitlement state",
|
|
59
|
+
install: "authenticate if needed, then install or upgrade the official bundle",
|
|
60
|
+
update: "upgrade an existing official bundle when a compatible release exists",
|
|
61
|
+
uninstall: "remove official plugin executables while preserving user data",
|
|
62
|
+
manage: "open the AgentMemory account and billing website",
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const WORKER_ACTION_DESCRIPTIONS: Record<(typeof WORKER_ACTIONS)[number], string> = {};
|
|
66
|
+
|
|
67
|
+
export const SCRATCHPAD_ACTION_DESCRIPTIONS: Record<(typeof SCRATCHPAD_ACTIONS)[number], string> = {
|
|
68
|
+
add: "add a new open checklist item; requires --text",
|
|
69
|
+
done: "complete the first open substring match; requires --text",
|
|
70
|
+
undo: "reopen the first completed substring match; requires --text",
|
|
71
|
+
clear_done: "remove every completed checklist item",
|
|
72
|
+
list: "show checklist items and completion counts",
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const GLOBAL_OPTIONS = ["--dir", "--json", "--help", "--version", "-h", "-V"] as const;
|
|
76
|
+
|
|
77
|
+
export const COMMAND_OPTIONS: Record<string, readonly string[]> = {
|
|
78
|
+
context: ["--query", "--no-search"],
|
|
79
|
+
write: ["--content", "--target", "--mode", "--topic", "--date", "--source-uri"],
|
|
80
|
+
read: ["--target", "--date", "--topic"],
|
|
81
|
+
scratchpad: ["--text"],
|
|
82
|
+
search: ["--query", "--mode", "--limit"],
|
|
83
|
+
distil: ["--dry-run"],
|
|
84
|
+
sync: [],
|
|
85
|
+
init: [],
|
|
86
|
+
status: ["--probe"],
|
|
87
|
+
"install-skills": [],
|
|
88
|
+
"uninstall-skills": [],
|
|
89
|
+
"install-hooks": ["--yes", "--all", "--only"],
|
|
90
|
+
"uninstall-hooks": ["--only"],
|
|
91
|
+
completion: ["--stdout"],
|
|
92
|
+
version: [],
|
|
93
|
+
help: [],
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const PLUGIN_COMMAND_OPTIONS: Record<string, readonly string[]> = {
|
|
97
|
+
list: [],
|
|
98
|
+
status: ["--channel"],
|
|
99
|
+
install: ["--channel", "--no-browser", "--yes"],
|
|
100
|
+
update: ["--channel"],
|
|
101
|
+
uninstall: ["--yes"],
|
|
102
|
+
manage: ["--no-browser"],
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const WORKER_ACTION_OPTIONS: Record<string, readonly string[]> = {};
|
|
106
|
+
|
|
107
|
+
export const SCRATCHPAD_ACTION_OPTIONS: Record<string, readonly string[]> = {
|
|
108
|
+
add: ["--text"],
|
|
109
|
+
done: ["--text"],
|
|
110
|
+
undo: ["--text"],
|
|
111
|
+
clear_done: [],
|
|
112
|
+
list: [],
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const OPTION_SPECS: Record<string, CliOptionSpec> = {
|
|
116
|
+
"--dir": { description: "override the active memory directory", value: { label: "directory", kind: "directory" } },
|
|
117
|
+
"--json": { description: "emit command-specific structured JSON" },
|
|
118
|
+
"--help": { description: "show help for the selected command" },
|
|
119
|
+
"--version": { description: "print the installed version and exit" },
|
|
120
|
+
"-h": { description: "show help for the selected command" },
|
|
121
|
+
"-V": { description: "print the installed version and exit" },
|
|
122
|
+
"--query": { description: "memory search or context-retrieval query", value: { label: "text", kind: "value" } },
|
|
123
|
+
"--no-search": { description: "build context without invoking qmd" },
|
|
124
|
+
"--content": { description: "memory entry content to persist", value: { label: "text", kind: "value" } },
|
|
125
|
+
"--target": { description: "memory destination or collection to read", value: { label: "target", kind: "value" } },
|
|
126
|
+
"--mode": { description: "write behavior or qmd search strategy", value: { label: "mode", kind: "value" } },
|
|
127
|
+
"--topic": { description: "topic name used to resolve a topic file", value: { label: "name", kind: "value" } },
|
|
128
|
+
"--date": { description: "daily-log date in YYYY-MM-DD form", value: { label: "date", kind: "value" } },
|
|
129
|
+
"--source-uri": {
|
|
130
|
+
description: "optional provenance URI stored with an entry",
|
|
131
|
+
value: { label: "uri", kind: "value" },
|
|
132
|
+
},
|
|
133
|
+
"--text": { description: "checklist item text or substring to match", value: { label: "text", kind: "value" } },
|
|
134
|
+
"--limit": { description: "maximum number of search or recall results", value: { label: "number", kind: "number" } },
|
|
135
|
+
"--dry-run": { description: "preview generated memory without writing MEMORY.md" },
|
|
136
|
+
"--probe": { description: "run a live semantic query to verify embeddings" },
|
|
137
|
+
"--since": { description: "metrics reporting window in days", value: { label: "days", kind: "number" } },
|
|
138
|
+
"--port": {
|
|
139
|
+
description: "web-console port; use 0 to select an available port",
|
|
140
|
+
value: { label: "number", kind: "number" },
|
|
141
|
+
},
|
|
142
|
+
"--state": { description: "override the plugin state root", value: { label: "directory", kind: "directory" } },
|
|
143
|
+
"--with-plugin": { description: "include both the core and optional plugin skills" },
|
|
144
|
+
"--plugin-only": { description: "operate only on the optional plugin skill" },
|
|
145
|
+
"--yes": { description: "apply eligible hook changes without confirmation" },
|
|
146
|
+
"--all": { description: "apply eligible hook changes without confirmation" },
|
|
147
|
+
"--only": {
|
|
148
|
+
description: "restrict hook changes to comma-separated agent keys",
|
|
149
|
+
value: { label: "agents", kind: "value" },
|
|
150
|
+
},
|
|
151
|
+
"--stdout": { description: "print the completion script without installing it" },
|
|
152
|
+
"--channel": {
|
|
153
|
+
description: "select the official release channel",
|
|
154
|
+
value: { label: "channel", kind: "value" },
|
|
155
|
+
},
|
|
156
|
+
"--no-browser": { description: "print account URLs instead of opening a browser" },
|
|
157
|
+
"--scope": {
|
|
158
|
+
description: "search globally or only in the current workspace",
|
|
159
|
+
value: { label: "scope", kind: "value" },
|
|
160
|
+
},
|
|
161
|
+
"--cwd": {
|
|
162
|
+
description: "restrict session operations to a working directory",
|
|
163
|
+
value: { label: "directory", kind: "directory" },
|
|
164
|
+
},
|
|
165
|
+
"--context": {
|
|
166
|
+
description: "surrounding events included with each recall hit",
|
|
167
|
+
value: { label: "number", kind: "number" },
|
|
168
|
+
},
|
|
169
|
+
"--pi": { description: "override the Pi session root", value: { label: "directory", kind: "directory" } },
|
|
170
|
+
"--codex": { description: "override the Codex session root", value: { label: "directory", kind: "directory" } },
|
|
171
|
+
"--claude": {
|
|
172
|
+
description: "override the Claude Code session root",
|
|
173
|
+
value: { label: "directory", kind: "directory" },
|
|
174
|
+
},
|
|
175
|
+
"--host": {
|
|
176
|
+
description: "session host (pi/codex/claude) or web loopback bind address",
|
|
177
|
+
value: { label: "host", kind: "value" },
|
|
178
|
+
},
|
|
179
|
+
"--max-per-host": {
|
|
180
|
+
description: "maximum session files read from each host",
|
|
181
|
+
value: { label: "number", kind: "number" },
|
|
182
|
+
},
|
|
183
|
+
"--recent": {
|
|
184
|
+
description: "most recently modified session files refreshed per host",
|
|
185
|
+
value: { label: "number", kind: "number" },
|
|
186
|
+
},
|
|
187
|
+
"--interval": {
|
|
188
|
+
description: "watch polling interval in milliseconds",
|
|
189
|
+
value: { label: "milliseconds", kind: "number" },
|
|
190
|
+
},
|
|
191
|
+
"--once": { description: "run one watch iteration and exit" },
|
|
192
|
+
"--lines": {
|
|
193
|
+
description: "number of recent worker log entries to return",
|
|
194
|
+
value: { label: "number", kind: "number" },
|
|
195
|
+
},
|
|
196
|
+
"--threshold": {
|
|
197
|
+
description: "minimum repeated evidence required for a candidate",
|
|
198
|
+
value: { label: "number", kind: "number" },
|
|
199
|
+
},
|
|
200
|
+
"--output": { description: "also write the report to this file", value: { label: "file", kind: "file" } },
|
|
201
|
+
"--replay": { description: "back up and rebuild derived learning layers" },
|
|
202
|
+
"--journal": {
|
|
203
|
+
description: "override the experience journal directory",
|
|
204
|
+
value: { label: "directory", kind: "directory" },
|
|
205
|
+
},
|
|
206
|
+
"--candidates-dir": {
|
|
207
|
+
description: "override the candidate ledger directory",
|
|
208
|
+
value: { label: "directory", kind: "directory" },
|
|
209
|
+
},
|
|
210
|
+
"--decisions-dir": {
|
|
211
|
+
description: "override the decision ledger directory",
|
|
212
|
+
value: { label: "directory", kind: "directory" },
|
|
213
|
+
},
|
|
214
|
+
"--auto-dir": {
|
|
215
|
+
description: "override the materialized auto-memory directory",
|
|
216
|
+
value: { label: "directory", kind: "directory" },
|
|
217
|
+
},
|
|
218
|
+
"--agent": { description: "internal SessionStart host key", value: { label: "agent", kind: "value" } },
|
|
219
|
+
"--token": { description: "internal session-worker lease token", value: { label: "token", kind: "value" } },
|
|
220
|
+
"--uninstall": { description: "use install-skills compatibility uninstall mode" },
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export const SHELL_DESCRIPTIONS: Record<string, string> = {
|
|
224
|
+
bash: "generate or install Bash completion",
|
|
225
|
+
zsh: "generate or install Zsh completion",
|
|
226
|
+
fish: "generate or install Fish completion",
|
|
227
|
+
powershell: "generate or install PowerShell completion",
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export function optionDescription(option: string): string {
|
|
231
|
+
return OPTION_SPECS[option]?.description ?? option;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function optionTakesValue(option: string): boolean {
|
|
235
|
+
return OPTION_SPECS[option]?.value !== undefined;
|
|
236
|
+
}
|