memorix 1.4.5 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/CLAUDE.md +7 -3
- package/README.md +5 -2
- package/dist/cli/index.js +1470 -1014
- package/dist/index.js +1279 -989
- package/dist/{maintenance-jobs-B1-W0ssz.d.ts → maintenance-jobs-DVRF-46r.d.ts} +1 -1
- package/dist/maintenance-runner.d.ts +1 -1
- package/dist/maintenance-runner.js +1769 -830
- package/dist/media-audio-runner.js +1774 -836
- package/dist/media-video-runner.js +1769 -831
- package/dist/memcode-runtime/CHANGELOG.md +78 -0
- package/dist/sdk.js +1271 -988
- package/dist/types.d.ts +6 -0
- package/dist/vector-backfill-runner.d.ts +1 -1
- package/dist/vector-backfill-runner.js +1765 -827
- package/docs/1.4.5-AGENT-AUTO-MEMORY-RESEARCH.md +95 -0
- package/docs/API_REFERENCE.md +23 -4
- package/docs/CONFIGURATION.md +29 -3
- package/docs/SETUP.md +5 -3
- package/package.json +1 -1
- package/plugins/antigravity/memorix/mcp_config.json +3 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/memorix/.mcp.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.mcp.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.mcp.json +1 -1
- package/plugins/copilot/memorix/.mcp.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +4 -2
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/openclaw/memorix/.mcp.json +3 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/commands/dashboard.ts +14 -3
- package/src/cli/commands/ingest-commit.ts +47 -3
- package/src/cli/commands/memory.ts +17 -4
- package/src/cli/commands/purge.ts +120 -0
- package/src/cli/commands/serve-http.ts +39 -5
- package/src/cli/commands/setup.ts +3 -1
- package/src/cli/index.ts +3 -804
- package/src/codegraph/auto-context.ts +82 -1
- package/src/config/yaml-loader.ts +3 -8
- package/src/config.ts +23 -7
- package/src/evaluation/session-replay.ts +98 -0
- package/src/git/extractor.ts +5 -3
- package/src/hooks/installers/index.ts +15 -0
- package/src/knowledge/workset.ts +58 -0
- package/src/memory/long-term.ts +97 -2
- package/src/runtime/control-plane-maintenance.ts +1 -0
- package/src/runtime/isolated-maintenance.ts +1 -0
- package/src/runtime/lifecycle.ts +19 -0
- package/src/runtime/maintenance-jobs.ts +1 -0
- package/src/runtime/project-maintenance.ts +8 -0
- package/src/search/surfaced-registry.ts +62 -0
- package/src/server.ts +74 -14
- package/src/store/orama-store.ts +17 -1
- package/src/types.ts +6 -0
- package/src/cli/commands/audit-list.ts +0 -89
- package/src/cli/commands/purge-all-memory.ts +0 -85
- package/src/cli/commands/purge-project-memory.ts +0 -83
- package/src/cli/commands/uninstall-project-artifacts.ts +0 -86
- package/src/cli/tui/Sidebar.tsx +0 -179
- package/src/cli/tui/interactive-commands.ts +0 -261
- package/src/cli/tui/markdown-render.tsx +0 -371
- package/src/cli/tui/use-mouse.ts +0 -157
- package/src/cli/tui/useNavigation.ts +0 -56
- package/src/orchestrate/context-compact.ts +0 -188
- package/src/team/file-locks.ts +0 -173
- package/src/team/index.ts +0 -23
- package/src/team/messages.ts +0 -203
- package/src/team/persistence.ts +0 -96
- package/src/team/registry.ts +0 -158
- package/src/team/tasks.ts +0 -211
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: memorix purge
|
|
3
|
+
*
|
|
4
|
+
* Retire memories from retrieval. Project-scoped by default; --all covers
|
|
5
|
+
* every project. Observations and long-term records are archived (never
|
|
6
|
+
* hard-deleted) so the audit trail survives. Refuses to run outside a
|
|
7
|
+
* terminal without --yes.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { defineCommand } from 'citty';
|
|
11
|
+
import { detectProject } from '../../project/detector.js';
|
|
12
|
+
import { getProjectDataDir } from '../../store/persistence.js';
|
|
13
|
+
|
|
14
|
+
export default defineCommand({
|
|
15
|
+
meta: {
|
|
16
|
+
name: 'purge',
|
|
17
|
+
description: 'Retire memories from retrieval (current project by default, --all for every project)',
|
|
18
|
+
},
|
|
19
|
+
args: {
|
|
20
|
+
all: {
|
|
21
|
+
type: 'boolean',
|
|
22
|
+
description: 'Purge every project instead of the current one',
|
|
23
|
+
default: false,
|
|
24
|
+
},
|
|
25
|
+
yes: {
|
|
26
|
+
type: 'boolean',
|
|
27
|
+
description: 'Skip the interactive confirmation',
|
|
28
|
+
default: false,
|
|
29
|
+
},
|
|
30
|
+
json: {
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
description: 'Emit a machine-readable result',
|
|
33
|
+
default: false,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
async run({ args }) {
|
|
37
|
+
const purgeAll = Boolean(args.all);
|
|
38
|
+
const yes = Boolean(args.yes);
|
|
39
|
+
const asJson = Boolean(args.json);
|
|
40
|
+
|
|
41
|
+
// Confirmation gate first: a destructive wipe never proceeds in a
|
|
42
|
+
// non-interactive shell without an explicit --yes.
|
|
43
|
+
if (!yes && !process.stdin.isTTY) {
|
|
44
|
+
console.error('[ERROR] Non-interactive environment. Add --yes to confirm.');
|
|
45
|
+
console.error('[ERROR] Refusing to purge memories without confirmation.');
|
|
46
|
+
process.exitCode = 1;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!yes) {
|
|
50
|
+
const readline = await import('node:readline');
|
|
51
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
52
|
+
const question = purgeAll
|
|
53
|
+
? 'Retire ALL memories from every project? (y/N) '
|
|
54
|
+
: 'Retire all memories for this project? (y/N) ';
|
|
55
|
+
const answer = await new Promise<string>((resolve) => rl.question(question, resolve));
|
|
56
|
+
rl.close();
|
|
57
|
+
if (answer.trim().toLowerCase() !== 'y') {
|
|
58
|
+
console.log('Cancelled.');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let projectId: string | null = null;
|
|
64
|
+
if (!purgeAll) {
|
|
65
|
+
const project = detectProject();
|
|
66
|
+
if (!project) {
|
|
67
|
+
console.error('[ERROR] No .git found — run from a project directory or pass --all.');
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
projectId = project.id;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const dataDir = await getProjectDataDir(projectId ?? '');
|
|
75
|
+
const { initObservationStore } = await import('../../store/obs-store.js');
|
|
76
|
+
const { getAllObservations, resolveObservations } = await import('../../memory/observations.js');
|
|
77
|
+
const { withFreshIndex } = await import('../../memory/freshness.js');
|
|
78
|
+
await initObservationStore(dataDir);
|
|
79
|
+
|
|
80
|
+
const observations = await withFreshIndex(() => getAllObservations());
|
|
81
|
+
const target = purgeAll ? observations : observations.filter((o) => o.projectId === projectId);
|
|
82
|
+
const ids = target
|
|
83
|
+
.map((o) => o.id)
|
|
84
|
+
.filter((id): id is number => typeof id === 'number');
|
|
85
|
+
const archived = ids.length > 0
|
|
86
|
+
? (await resolveObservations(ids, 'archived')).resolved.length
|
|
87
|
+
: 0;
|
|
88
|
+
|
|
89
|
+
const { LongTermMemoryStore } = await import('../../memory/long-term-store.js');
|
|
90
|
+
const { archiveLongTermMemory } = await import('../../memory/long-term.js');
|
|
91
|
+
const longTermStore = new LongTermMemoryStore();
|
|
92
|
+
await longTermStore.init(dataDir);
|
|
93
|
+
let longTermArchived = 0;
|
|
94
|
+
for (const memory of longTermStore.list()) {
|
|
95
|
+
if (memory.state === 'archived' || memory.state === 'superseded') continue;
|
|
96
|
+
if (!purgeAll && memory.originProjectId !== projectId) continue;
|
|
97
|
+
try {
|
|
98
|
+
await archiveLongTermMemory({
|
|
99
|
+
dataDir,
|
|
100
|
+
id: memory.id,
|
|
101
|
+
reason: purgeAll ? 'purge --all' : 'purge (project) ' + (projectId ?? ''),
|
|
102
|
+
});
|
|
103
|
+
longTermArchived += 1;
|
|
104
|
+
} catch { /* already inactive */ }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const result = {
|
|
108
|
+
scope: purgeAll ? 'all' : projectId,
|
|
109
|
+
observationsArchived: archived,
|
|
110
|
+
longTermArchived,
|
|
111
|
+
};
|
|
112
|
+
if (asJson) {
|
|
113
|
+
console.log(JSON.stringify(result));
|
|
114
|
+
} else {
|
|
115
|
+
console.log(
|
|
116
|
+
`[OK] Purged ${purgeAll ? 'all projects' : result.scope}: archived ${archived} observations and ${longTermArchived} long-term memories.`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
});
|
|
@@ -39,6 +39,36 @@ export function parseSessionTimeoutMs(raw: string | undefined): number {
|
|
|
39
39
|
return Math.floor(parsed);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
export interface ServeHttpConfiguredDefaults {
|
|
43
|
+
port?: number;
|
|
44
|
+
transport?: 'stdio' | 'http';
|
|
45
|
+
dashboard?: boolean;
|
|
46
|
+
dashboardPort?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The [server] config section is a real default source, not display-only:
|
|
51
|
+
* `port` becomes the listener default and an explicit `transport: "stdio"`
|
|
52
|
+
* produces a notice (an explicit serve-http command still wins). CLI flags
|
|
53
|
+
* always beat config.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveServeHttpDefaults(
|
|
56
|
+
argsPort: string | undefined,
|
|
57
|
+
configured: ServeHttpConfiguredDefaults,
|
|
58
|
+
): { port: number; transportNotice?: string } {
|
|
59
|
+
const configuredPort = typeof configured.port === 'number' && Number.isFinite(configured.port)
|
|
60
|
+
? configured.port
|
|
61
|
+
: undefined;
|
|
62
|
+
const port = parseTcpPortOrReport(argsPort, configuredPort ?? 3211);
|
|
63
|
+
if (port === undefined) {
|
|
64
|
+
return { port: 3211 };
|
|
65
|
+
}
|
|
66
|
+
const transportNotice = configured.transport === 'stdio'
|
|
67
|
+
? '[memorix] config server.transport = "stdio"; serve-http continues on HTTP (the explicit command wins).'
|
|
68
|
+
: undefined;
|
|
69
|
+
return { port, transportNotice };
|
|
70
|
+
}
|
|
71
|
+
|
|
42
72
|
export default defineCommand({
|
|
43
73
|
meta: {
|
|
44
74
|
name: 'serve-http',
|
|
@@ -81,11 +111,15 @@ export default defineCommand({
|
|
|
81
111
|
const { writeFileSync, mkdirSync } = await import('node:fs');
|
|
82
112
|
const { homedir } = await import('node:os');
|
|
83
113
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
114
|
+
// The [server] config section feeds startup defaults; CLI flags win.
|
|
115
|
+
let configuredDefaults: ServeHttpConfiguredDefaults = {};
|
|
116
|
+
try {
|
|
117
|
+
const { getServerConfig } = await import('../../config.js');
|
|
118
|
+
configuredDefaults = getServerConfig();
|
|
119
|
+
} catch { /* config files are optional */ }
|
|
120
|
+
const resolved = resolveServeHttpDefaults(args.port as string | undefined, configuredDefaults);
|
|
121
|
+
if (resolved.transportNotice) console.error(resolved.transportNotice);
|
|
122
|
+
const port = resolved.port;
|
|
89
123
|
const host = args.host || '127.0.0.1';
|
|
90
124
|
const toolProfile = resolveToolProfile({ explicit: args.mode, envValue: process.env.MEMORIX_MODE, fallback: 'team' });
|
|
91
125
|
|
|
@@ -422,7 +422,9 @@ export function buildMemorixServer(mcp: Exclude<SetupMcpTransport, 'none'>): MCP
|
|
|
422
422
|
return {
|
|
423
423
|
name: 'memorix',
|
|
424
424
|
command: 'memorix',
|
|
425
|
-
|
|
425
|
+
// The installed surface must expose every tool the generated guidance
|
|
426
|
+
// teaches. lite covers the full taught set; micro would hide half of it.
|
|
427
|
+
args: ['serve', '--mode', 'lite'],
|
|
426
428
|
};
|
|
427
429
|
}
|
|
428
430
|
|