@ghl-ai/aw 0.1.37-beta.44 → 0.1.37-beta.46
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/commands/init.mjs +3 -1
- package/commands/memory.mjs +73 -8
- package/constants.mjs +3 -0
- package/ecc.mjs +1 -1
- package/memory-bridge.mjs +80 -6
- package/memory-queue.mjs +13 -10
- package/package.json +2 -2
package/commands/init.mjs
CHANGED
|
@@ -353,7 +353,6 @@ export async function initCommand(args) {
|
|
|
353
353
|
try {
|
|
354
354
|
await initPersistentClone(repoUrl, AW_HOME, sparsePaths);
|
|
355
355
|
ensureAwGitignore(AW_HOME);
|
|
356
|
-
mkdirSync(join(GLOBAL_AW_DIR, 'memory'), { recursive: true });
|
|
357
356
|
s.stop('Registry cloned');
|
|
358
357
|
} catch (e) {
|
|
359
358
|
s.stop(chalk.red('Clone failed'));
|
|
@@ -382,6 +381,9 @@ export async function initCommand(args) {
|
|
|
382
381
|
}
|
|
383
382
|
}
|
|
384
383
|
|
|
384
|
+
// Create memory dir after symlink so GLOBAL_AW_DIR resolves correctly
|
|
385
|
+
mkdirSync(join(GLOBAL_AW_DIR, 'memory'), { recursive: true });
|
|
386
|
+
|
|
385
387
|
// Create sync config — default to 'platform' when no namespace specified
|
|
386
388
|
const cfg = config.create(GLOBAL_AW_DIR, { namespace: team || 'platform', user });
|
|
387
389
|
if (folderName) {
|
package/commands/memory.mjs
CHANGED
|
@@ -6,10 +6,32 @@ import { homedir } from 'node:os';
|
|
|
6
6
|
import { confirm, isCancel, text } from '@clack/prompts';
|
|
7
7
|
import * as fmt from '../fmt.mjs';
|
|
8
8
|
import { chalk } from '../fmt.mjs';
|
|
9
|
-
import { callMemoryTool } from '../memory-bridge.mjs';
|
|
9
|
+
import { callMemoryTool, computeAncestry, resolveStoreNamespace, resolveReadPaths } from '../memory-bridge.mjs';
|
|
10
10
|
import { syncMemories } from '../memory-sync.mjs';
|
|
11
|
-
import { REGISTRY_DIR } from '../constants.mjs';
|
|
11
|
+
import { REGISTRY_DIR, ORG_SCOPE_NAMESPACE } from '../constants.mjs';
|
|
12
12
|
import { getQueueStats } from '../memory-queue.mjs';
|
|
13
|
+
import * as config from '../config.mjs';
|
|
14
|
+
|
|
15
|
+
/** Load .sync-config.json from the registry directory. */
|
|
16
|
+
function loadCfg() {
|
|
17
|
+
const registryDir = join(homedir(), '.aw', REGISTRY_DIR);
|
|
18
|
+
return config.load(registryDir) || {};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Validate that an explicit namespace is within the user's ancestry chain.
|
|
23
|
+
* Returns true if valid, false if not.
|
|
24
|
+
*/
|
|
25
|
+
function validateNamespaceAccess(cfg, explicitNs) {
|
|
26
|
+
const includes = cfg.include || [];
|
|
27
|
+
// Build full ancestry from the user's include paths
|
|
28
|
+
const validPaths = includes.length > 0
|
|
29
|
+
? computeAncestry(includes)
|
|
30
|
+
: [cfg.namespace || ORG_SCOPE_NAMESPACE];
|
|
31
|
+
// Always allow the org root
|
|
32
|
+
if (!validPaths.includes(ORG_SCOPE_NAMESPACE)) validPaths.push(ORG_SCOPE_NAMESPACE);
|
|
33
|
+
return validPaths.includes(explicitNs);
|
|
34
|
+
}
|
|
13
35
|
|
|
14
36
|
// ── legacy import ─────────────────────────────────────────────────────
|
|
15
37
|
|
|
@@ -155,18 +177,34 @@ async function memoryStore(args) {
|
|
|
155
177
|
|
|
156
178
|
fmt.intro('aw memory store');
|
|
157
179
|
|
|
180
|
+
const cfg = loadCfg();
|
|
181
|
+
const explicitNs = args['--namespace'] || null;
|
|
182
|
+
|
|
183
|
+
// Validate explicit namespace is within ancestry chain
|
|
184
|
+
if (explicitNs && !validateNamespaceAccess(cfg, explicitNs)) {
|
|
185
|
+
fmt.cancel(`Namespace "${explicitNs}" is not in your ancestry chain. Your include paths: ${(cfg.include || []).join(', ') || '(none)'}`);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Resolve store namespace via layered defaults
|
|
190
|
+
const storeNs = resolveStoreNamespace(cfg, explicitNs);
|
|
191
|
+
|
|
158
192
|
const params = { content };
|
|
159
193
|
if (args['--type']) params.type = args['--type'];
|
|
160
|
-
if (
|
|
194
|
+
if (storeNs) params.namespace = storeNs;
|
|
161
195
|
if (args['--layer']) params.layer = args['--layer'];
|
|
162
196
|
if (args['--overlay']) params.overlay = args['--overlay'].split(',').map(s => s.trim());
|
|
163
197
|
if (args['--angle']) params.angle = args['--angle'].split(',').map(s => s.trim());
|
|
164
198
|
if (args['--tags']) params.tags = args['--tags'].split(',').map(s => s.trim());
|
|
165
199
|
|
|
200
|
+
// Build call opts
|
|
201
|
+
const callOpts = {};
|
|
202
|
+
if (storeNs) callOpts.storeNamespace = storeNs;
|
|
203
|
+
|
|
166
204
|
const s = fmt.spinner();
|
|
167
205
|
s.start('Storing memory...');
|
|
168
206
|
try {
|
|
169
|
-
const result = await callMemoryTool('memory_curated_store', params);
|
|
207
|
+
const result = await callMemoryTool('memory_curated_store', params, callOpts);
|
|
170
208
|
s.stop('Memory stored');
|
|
171
209
|
|
|
172
210
|
const data = result?.result ?? result;
|
|
@@ -203,17 +241,29 @@ async function memorySearch(args) {
|
|
|
203
241
|
|
|
204
242
|
fmt.intro('aw memory search');
|
|
205
243
|
|
|
244
|
+
const cfg = loadCfg();
|
|
245
|
+
const explicitNs = args['--namespace'] || null;
|
|
246
|
+
|
|
247
|
+
// Resolve read paths via layered defaults
|
|
248
|
+
const readPaths = resolveReadPaths(cfg, explicitNs);
|
|
249
|
+
|
|
206
250
|
const params = { query };
|
|
207
|
-
if (
|
|
251
|
+
if (explicitNs) params.namespace = explicitNs;
|
|
208
252
|
if (args['--limit']) params.limit = parseInt(args['--limit'], 10);
|
|
209
253
|
if (args['--layer']) params.layer = args['--layer'];
|
|
210
254
|
if (args['--overlay']) params.overlay = args['--overlay'];
|
|
211
255
|
if (args['--angle']) params.angle = args['--angle'];
|
|
212
256
|
|
|
257
|
+
// Override namespace paths header when explicit ns is provided
|
|
258
|
+
const callOpts = {};
|
|
259
|
+
if (explicitNs) {
|
|
260
|
+
callOpts.namespacePaths = readPaths.join(',');
|
|
261
|
+
}
|
|
262
|
+
|
|
213
263
|
const s = fmt.spinner();
|
|
214
264
|
s.start('Searching memories...');
|
|
215
265
|
try {
|
|
216
|
-
const result = await callMemoryTool('memory_search', params);
|
|
266
|
+
const result = await callMemoryTool('memory_search', params, callOpts);
|
|
217
267
|
s.stop('Search complete');
|
|
218
268
|
|
|
219
269
|
const memories = Array.isArray(result) ? result : (result?.memories ?? result?.results ?? []);
|
|
@@ -259,18 +309,30 @@ async function memoryPack(args) {
|
|
|
259
309
|
|
|
260
310
|
fmt.intro('aw memory pack');
|
|
261
311
|
|
|
312
|
+
const cfg = loadCfg();
|
|
313
|
+
const explicitNs = args['--namespace'] || null;
|
|
314
|
+
|
|
315
|
+
// Resolve read paths via layered defaults (same as search)
|
|
316
|
+
const readPaths = resolveReadPaths(cfg, explicitNs);
|
|
317
|
+
|
|
262
318
|
const params = { query };
|
|
263
|
-
if (
|
|
319
|
+
if (explicitNs) params.namespace = explicitNs;
|
|
264
320
|
if (args['--budget']) params.token_budget = parseInt(args['--budget'], 10);
|
|
265
321
|
else params.token_budget = 3500;
|
|
266
322
|
if (args['--layer']) params.layer = args['--layer'];
|
|
267
323
|
if (args['--overlay']) params.overlay = args['--overlay'];
|
|
268
324
|
if (args['--angle']) params.angle = args['--angle'];
|
|
269
325
|
|
|
326
|
+
// Override namespace paths header when explicit ns is provided
|
|
327
|
+
const callOpts = {};
|
|
328
|
+
if (explicitNs) {
|
|
329
|
+
callOpts.namespacePaths = readPaths.join(',');
|
|
330
|
+
}
|
|
331
|
+
|
|
270
332
|
const s = fmt.spinner();
|
|
271
333
|
s.start('Building memory pack...');
|
|
272
334
|
try {
|
|
273
|
-
const result = await callMemoryTool('memory_pack', params);
|
|
335
|
+
const result = await callMemoryTool('memory_pack', params, callOpts);
|
|
274
336
|
s.stop('Pack ready');
|
|
275
337
|
|
|
276
338
|
const pack = result?.pack ?? result?.content ?? result;
|
|
@@ -1261,3 +1323,6 @@ function memoryHelp() {
|
|
|
1261
1323
|
|
|
1262
1324
|
console.log(help);
|
|
1263
1325
|
}
|
|
1326
|
+
|
|
1327
|
+
// ── test-only exports ────────────────────────────────────────────────
|
|
1328
|
+
export const _test = { rateMemoryQuality, getQualityIssue, buildPromoteContent, normalizeForGrouping, formatTimeAgo };
|
package/constants.mjs
CHANGED
|
@@ -37,3 +37,6 @@ export const AW_CO_AUTHOR = `Co-Authored-By: ${AW_BOT_NAME} <${AW_BOT_EMAIL}>`;
|
|
|
37
37
|
|
|
38
38
|
/** MCP base URL for memory and other tool calls — override with AW_MCP_URL env var */
|
|
39
39
|
export const MCP_BASE_URL = process.env.AW_MCP_URL || 'http://localhost:3100/agentic-workspace/mcp';
|
|
40
|
+
|
|
41
|
+
/** Default org-level namespace — always included in ancestry */
|
|
42
|
+
export const ORG_SCOPE_NAMESPACE = 'platform';
|
package/ecc.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import * as fmt from "./fmt.mjs";
|
|
|
9
9
|
|
|
10
10
|
const AW_ECC_REPO_SSH = "git@github.com:shreyansh-ghl/aw-ecc.git";
|
|
11
11
|
const AW_ECC_REPO_HTTPS = "https://github.com/shreyansh-ghl/aw-ecc.git";
|
|
12
|
-
const AW_ECC_TAG = "v1.4.
|
|
12
|
+
const AW_ECC_TAG = "v1.4.3";
|
|
13
13
|
|
|
14
14
|
const MARKETPLACE_NAME = "aw-marketplace";
|
|
15
15
|
const PLUGIN_KEY = `aw@${MARKETPLACE_NAME}`;
|
package/memory-bridge.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { execSync } from 'node:child_process';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
-
import { MCP_BASE_URL, AW_HOME, REGISTRY_DIR } from './constants.mjs';
|
|
5
|
+
import { MCP_BASE_URL, AW_HOME, REGISTRY_DIR, ORG_SCOPE_NAMESPACE } from './constants.mjs';
|
|
6
6
|
import * as config from './config.mjs';
|
|
7
7
|
import { enqueue, flushQueue } from './memory-queue.mjs';
|
|
8
8
|
|
|
@@ -24,9 +24,21 @@ function resolveHeaders() {
|
|
|
24
24
|
'Accept': 'application/json, text/event-stream',
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
// Resolve namespace from .sync-config.json
|
|
27
|
+
// Resolve namespace paths from .sync-config.json
|
|
28
28
|
const registryDir = join(AW_HOME, REGISTRY_DIR);
|
|
29
29
|
const cfg = config.load(registryDir);
|
|
30
|
+
|
|
31
|
+
// Send ALL initialized namespace paths (from include[]) + platform
|
|
32
|
+
const paths = [...(cfg?.include || [])];
|
|
33
|
+
if (!paths.some(p => p === ORG_SCOPE_NAMESPACE || p.startsWith(ORG_SCOPE_NAMESPACE + '/'))) {
|
|
34
|
+
paths.push(ORG_SCOPE_NAMESPACE);
|
|
35
|
+
}
|
|
36
|
+
headers['X-Namespace-Paths'] = paths.join(',');
|
|
37
|
+
|
|
38
|
+
// Send GitHub username
|
|
39
|
+
headers['X-Github-User'] = cfg?.user || '';
|
|
40
|
+
|
|
41
|
+
// Keep X-Namespace for backwards compat
|
|
30
42
|
if (cfg?.namespace) {
|
|
31
43
|
headers['X-Namespace'] = cfg.namespace;
|
|
32
44
|
}
|
|
@@ -56,6 +68,57 @@ function resolveGhToken() {
|
|
|
56
68
|
return null;
|
|
57
69
|
}
|
|
58
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Compute the full ancestry chain for a set of namespace paths.
|
|
73
|
+
* E.g. ['platform/scheduling/calendars'] → ['platform/scheduling/calendars', 'platform/scheduling', 'platform']
|
|
74
|
+
*/
|
|
75
|
+
export function computeAncestry(paths) {
|
|
76
|
+
const result = new Set();
|
|
77
|
+
for (const path of paths) {
|
|
78
|
+
const segments = path.split('/');
|
|
79
|
+
for (let i = segments.length; i >= 1; i--) {
|
|
80
|
+
result.add(segments.slice(0, i).join('/'));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
result.add(ORG_SCOPE_NAMESPACE);
|
|
84
|
+
return [...result];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Resolve the store namespace using layered defaults.
|
|
89
|
+
* Layer 1: Explicit (from --namespace flag)
|
|
90
|
+
* Layer 2: Single include path
|
|
91
|
+
* Layer 3: Multi include — return null (curation picks)
|
|
92
|
+
* Layer 4: Fallback to cfg.namespace or 'platform'
|
|
93
|
+
*/
|
|
94
|
+
export function resolveStoreNamespace(cfg, explicitNs) {
|
|
95
|
+
// Layer 1: Explicit
|
|
96
|
+
if (explicitNs) return explicitNs;
|
|
97
|
+
// Layer 2: Single include
|
|
98
|
+
const includes = cfg?.include || [];
|
|
99
|
+
if (includes.length === 1) return includes[0];
|
|
100
|
+
// Layer 3: Multi include — return null (curation picks)
|
|
101
|
+
if (includes.length > 1) return null;
|
|
102
|
+
// Layer 4: Fallback
|
|
103
|
+
return cfg?.namespace || ORG_SCOPE_NAMESPACE;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Resolve read namespace paths using layered defaults.
|
|
108
|
+
* Returns a full ancestry chain for the resolved paths.
|
|
109
|
+
*/
|
|
110
|
+
export function resolveReadPaths(cfg, explicitNs) {
|
|
111
|
+
// Layer 1: Explicit
|
|
112
|
+
if (explicitNs) return computeAncestry([explicitNs]);
|
|
113
|
+
// Layer 2: Single include
|
|
114
|
+
const includes = cfg?.include || [];
|
|
115
|
+
if (includes.length === 1) return computeAncestry(includes);
|
|
116
|
+
// Layer 3: Multi include
|
|
117
|
+
if (includes.length > 1) return computeAncestry(includes);
|
|
118
|
+
// Layer 4: Fallback
|
|
119
|
+
return [ORG_SCOPE_NAMESPACE];
|
|
120
|
+
}
|
|
121
|
+
|
|
59
122
|
/** Write operations that can be queued when MCP is unreachable. */
|
|
60
123
|
const WRITE_OPS = new Set([
|
|
61
124
|
'memory_store',
|
|
@@ -112,11 +175,14 @@ async function tryFlushQueue() {
|
|
|
112
175
|
* - On success, flushes any queued operations
|
|
113
176
|
* @param {string} toolName — MCP tool name (e.g. 'memory_curated_store', 'memory_search')
|
|
114
177
|
* @param {object} params — Tool arguments
|
|
178
|
+
* @param {object} [opts] — Optional overrides
|
|
179
|
+
* @param {string} [opts.storeNamespace] — If set, adds X-Store-Namespace header
|
|
180
|
+
* @param {string} [opts.namespacePaths] — If set, overrides X-Namespace-Paths header
|
|
115
181
|
* @returns {Promise<object>} Parsed tool result (or synthetic {queued:true})
|
|
116
182
|
*/
|
|
117
|
-
export async function callMemoryTool(toolName, params) {
|
|
183
|
+
export async function callMemoryTool(toolName, params, opts = {}) {
|
|
118
184
|
try {
|
|
119
|
-
const result = await _callMemoryToolRaw(toolName, params);
|
|
185
|
+
const result = await _callMemoryToolRaw(toolName, params, opts);
|
|
120
186
|
// MCP is reachable — flush any queued items in the background
|
|
121
187
|
tryFlushQueue();
|
|
122
188
|
return result;
|
|
@@ -133,12 +199,20 @@ export async function callMemoryTool(toolName, params) {
|
|
|
133
199
|
* Raw MCP transport — JSON-RPC 2.0 over Streamable HTTP.
|
|
134
200
|
* @param {string} toolName
|
|
135
201
|
* @param {object} params
|
|
202
|
+
* @param {object} [opts]
|
|
136
203
|
* @returns {Promise<object>}
|
|
137
204
|
*/
|
|
138
|
-
async function _callMemoryToolRaw(toolName, params) {
|
|
205
|
+
async function _callMemoryToolRaw(toolName, params, opts = {}) {
|
|
206
|
+
const headers = { ...resolveHeaders() };
|
|
207
|
+
if (opts.storeNamespace) {
|
|
208
|
+
headers['X-Store-Namespace'] = opts.storeNamespace;
|
|
209
|
+
}
|
|
210
|
+
if (opts.namespacePaths) {
|
|
211
|
+
headers['X-Namespace-Paths'] = opts.namespacePaths;
|
|
212
|
+
}
|
|
139
213
|
const response = await fetch(MCP_BASE_URL, {
|
|
140
214
|
method: 'POST',
|
|
141
|
-
headers
|
|
215
|
+
headers,
|
|
142
216
|
body: JSON.stringify({
|
|
143
217
|
jsonrpc: '2.0',
|
|
144
218
|
id: _rpcId++,
|
package/memory-queue.mjs
CHANGED
|
@@ -4,8 +4,8 @@ import { readFileSync, writeFileSync, appendFileSync, existsSync, mkdirSync } fr
|
|
|
4
4
|
import { join, dirname } from 'node:path';
|
|
5
5
|
import { AW_HOME } from './constants.mjs';
|
|
6
6
|
|
|
7
|
-
/** Queue file path: ~/.aw/memory-queue.jsonl */
|
|
8
|
-
|
|
7
|
+
/** Queue file path: ~/.aw/memory-queue.jsonl (resolved lazily for testability) */
|
|
8
|
+
function getQueuePath() { return join(AW_HOME, 'memory-queue.jsonl'); }
|
|
9
9
|
|
|
10
10
|
/** Max age for queued items before they are discarded (7 days in ms) */
|
|
11
11
|
const MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
@@ -16,7 +16,8 @@ const MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
|
16
16
|
* @param {object} payload — Tool arguments
|
|
17
17
|
*/
|
|
18
18
|
export function enqueue(op, payload) {
|
|
19
|
-
const
|
|
19
|
+
const queuePath = getQueuePath();
|
|
20
|
+
const dir = dirname(queuePath);
|
|
20
21
|
if (!existsSync(dir)) {
|
|
21
22
|
mkdirSync(dir, { recursive: true });
|
|
22
23
|
}
|
|
@@ -28,7 +29,7 @@ export function enqueue(op, payload) {
|
|
|
28
29
|
attempt: 0,
|
|
29
30
|
};
|
|
30
31
|
|
|
31
|
-
appendFileSync(
|
|
32
|
+
appendFileSync(queuePath, JSON.stringify(entry) + '\n', 'utf8');
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -39,11 +40,12 @@ export function enqueue(op, payload) {
|
|
|
39
40
|
* @returns {Promise<{processed: number, failed: number, discarded: number}>}
|
|
40
41
|
*/
|
|
41
42
|
export async function flushQueue(sender) {
|
|
42
|
-
|
|
43
|
+
const queuePath = getQueuePath();
|
|
44
|
+
if (!existsSync(queuePath)) {
|
|
43
45
|
return { processed: 0, failed: 0, discarded: 0 };
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
const raw = readFileSync(
|
|
48
|
+
const raw = readFileSync(queuePath, 'utf8').trim();
|
|
47
49
|
if (!raw) {
|
|
48
50
|
return { processed: 0, failed: 0, discarded: 0 };
|
|
49
51
|
}
|
|
@@ -85,9 +87,9 @@ export async function flushQueue(sender) {
|
|
|
85
87
|
// Rewrite queue with only the remaining (failed) items
|
|
86
88
|
if (remaining.length > 0) {
|
|
87
89
|
const data = remaining.map(e => JSON.stringify(e)).join('\n') + '\n';
|
|
88
|
-
writeFileSync(
|
|
90
|
+
writeFileSync(queuePath, data, 'utf8');
|
|
89
91
|
} else {
|
|
90
|
-
writeFileSync(
|
|
92
|
+
writeFileSync(queuePath, '', 'utf8');
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
return { processed, failed, discarded };
|
|
@@ -98,11 +100,12 @@ export async function flushQueue(sender) {
|
|
|
98
100
|
* @returns {{pending: number, oldest: string|null, newest: string|null}}
|
|
99
101
|
*/
|
|
100
102
|
export function getQueueStats() {
|
|
101
|
-
|
|
103
|
+
const queuePath = getQueuePath();
|
|
104
|
+
if (!existsSync(queuePath)) {
|
|
102
105
|
return { pending: 0, oldest: null, newest: null };
|
|
103
106
|
}
|
|
104
107
|
|
|
105
|
-
const raw = readFileSync(
|
|
108
|
+
const raw = readFileSync(queuePath, 'utf8').trim();
|
|
106
109
|
if (!raw) {
|
|
107
110
|
return { pending: 0, oldest: null, newest: null };
|
|
108
111
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghl-ai/aw",
|
|
3
|
-
"version": "0.1.37-beta.
|
|
3
|
+
"version": "0.1.37-beta.46",
|
|
4
4
|
"description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "bin.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"scripts": {
|
|
47
47
|
"test": "yarn test:vitest && yarn test:node",
|
|
48
|
-
"test:vitest": "vitest run --reporter=verbose tests/commands tests/mcp.test.mjs tests/telemetry.test.mjs",
|
|
48
|
+
"test:vitest": "vitest run --reporter=verbose tests/commands tests/mcp.test.mjs tests/telemetry.test.mjs tests/memory-queue.test.mjs tests/memory-sync.test.mjs tests/memory-bridge.test.mjs",
|
|
49
49
|
"test:node": "node tests/run-node-tests.mjs",
|
|
50
50
|
"test:watch": "vitest --reporter=verbose tests/commands tests/mcp.test.mjs tests/telemetry.test.mjs",
|
|
51
51
|
"preuninstall": "node bin.js nuke 2>/dev/null || true"
|