chainlesschain 0.37.9 → 0.37.11
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 +309 -19
- package/bin/chainlesschain.js +4 -0
- package/package.json +1 -1
- package/src/commands/a2a.js +374 -0
- package/src/commands/audit.js +286 -0
- package/src/commands/auth.js +387 -0
- package/src/commands/bi.js +240 -0
- package/src/commands/browse.js +184 -0
- package/src/commands/cowork.js +317 -0
- package/src/commands/did.js +376 -0
- package/src/commands/economy.js +375 -0
- package/src/commands/encrypt.js +233 -0
- package/src/commands/evolution.js +398 -0
- package/src/commands/export.js +125 -0
- package/src/commands/git.js +215 -0
- package/src/commands/hmemory.js +273 -0
- package/src/commands/hook.js +260 -0
- package/src/commands/import.js +259 -0
- package/src/commands/init.js +184 -0
- package/src/commands/instinct.js +202 -0
- package/src/commands/llm.js +155 -4
- package/src/commands/lowcode.js +320 -0
- package/src/commands/mcp.js +302 -0
- package/src/commands/memory.js +282 -0
- package/src/commands/note.js +187 -0
- package/src/commands/org.js +505 -0
- package/src/commands/p2p.js +274 -0
- package/src/commands/plugin.js +451 -0
- package/src/commands/sandbox.js +366 -0
- package/src/commands/search.js +237 -0
- package/src/commands/session.js +238 -0
- package/src/commands/skill.js +254 -201
- package/src/commands/sync.js +249 -0
- package/src/commands/tokens.js +214 -0
- package/src/commands/wallet.js +416 -0
- package/src/commands/workflow.js +359 -0
- package/src/commands/zkp.js +277 -0
- package/src/index.js +93 -1
- package/src/lib/a2a-protocol.js +371 -0
- package/src/lib/agent-coordinator.js +273 -0
- package/src/lib/agent-economy.js +369 -0
- package/src/lib/app-builder.js +377 -0
- package/src/lib/audit-logger.js +364 -0
- package/src/lib/bi-engine.js +299 -0
- package/src/lib/bm25-search.js +322 -0
- package/src/lib/browser-automation.js +216 -0
- package/src/lib/cowork/ab-comparator-cli.js +180 -0
- package/src/lib/cowork/code-knowledge-graph-cli.js +232 -0
- package/src/lib/cowork/debate-review-cli.js +144 -0
- package/src/lib/cowork/decision-kb-cli.js +153 -0
- package/src/lib/cowork/project-style-analyzer-cli.js +168 -0
- package/src/lib/cowork-adapter.js +106 -0
- package/src/lib/crypto-manager.js +246 -0
- package/src/lib/did-manager.js +270 -0
- package/src/lib/ensure-utf8.js +59 -0
- package/src/lib/evolution-system.js +508 -0
- package/src/lib/git-integration.js +220 -0
- package/src/lib/hierarchical-memory.js +471 -0
- package/src/lib/hook-manager.js +387 -0
- package/src/lib/instinct-manager.js +190 -0
- package/src/lib/knowledge-exporter.js +302 -0
- package/src/lib/knowledge-importer.js +293 -0
- package/src/lib/llm-providers.js +325 -0
- package/src/lib/mcp-client.js +413 -0
- package/src/lib/memory-manager.js +211 -0
- package/src/lib/note-versioning.js +244 -0
- package/src/lib/org-manager.js +424 -0
- package/src/lib/p2p-manager.js +317 -0
- package/src/lib/pdf-parser.js +96 -0
- package/src/lib/permission-engine.js +374 -0
- package/src/lib/plan-mode.js +333 -0
- package/src/lib/plugin-manager.js +430 -0
- package/src/lib/project-detector.js +53 -0
- package/src/lib/response-cache.js +156 -0
- package/src/lib/sandbox-v2.js +503 -0
- package/src/lib/service-container.js +183 -0
- package/src/lib/session-manager.js +189 -0
- package/src/lib/skill-loader.js +274 -0
- package/src/lib/sync-manager.js +347 -0
- package/src/lib/token-tracker.js +200 -0
- package/src/lib/wallet-manager.js +348 -0
- package/src/lib/workflow-engine.js +503 -0
- package/src/lib/zkp-engine.js +241 -0
- package/src/repl/agent-repl.js +259 -124
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git integration commands
|
|
3
|
+
* chainlesschain git status|auto-commit|hooks|history-analyze
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { resolve } from "path";
|
|
8
|
+
import { logger } from "../lib/logger.js";
|
|
9
|
+
import {
|
|
10
|
+
gitStatus,
|
|
11
|
+
gitAutoCommit,
|
|
12
|
+
gitLog,
|
|
13
|
+
gitHistoryAnalyze,
|
|
14
|
+
gitInit,
|
|
15
|
+
isGitRepo,
|
|
16
|
+
} from "../lib/git-integration.js";
|
|
17
|
+
|
|
18
|
+
export function registerGitCommand(program) {
|
|
19
|
+
const git = program
|
|
20
|
+
.command("git")
|
|
21
|
+
.description("Git integration for knowledge base versioning");
|
|
22
|
+
|
|
23
|
+
// git status
|
|
24
|
+
git
|
|
25
|
+
.command("status")
|
|
26
|
+
.description("Show git status of the knowledge base directory")
|
|
27
|
+
.option("-d, --dir <dir>", "Target directory", ".")
|
|
28
|
+
.option("--json", "Output as JSON")
|
|
29
|
+
.action(async (options) => {
|
|
30
|
+
try {
|
|
31
|
+
const dir = resolve(options.dir);
|
|
32
|
+
const status = gitStatus(dir);
|
|
33
|
+
|
|
34
|
+
if (options.json) {
|
|
35
|
+
console.log(JSON.stringify(status, null, 2));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!status.isRepo) {
|
|
40
|
+
logger.info(
|
|
41
|
+
`Not a git repository: ${dir}\n Run ${chalk.cyan("chainlesschain git init")} to initialize.`,
|
|
42
|
+
);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
logger.log(chalk.bold(`Branch: ${chalk.cyan(status.branch)}`));
|
|
47
|
+
|
|
48
|
+
if (status.clean) {
|
|
49
|
+
logger.log(chalk.green("Working tree clean"));
|
|
50
|
+
} else {
|
|
51
|
+
logger.log(`\n${status.files.length} changed file(s):\n`);
|
|
52
|
+
for (const f of status.files) {
|
|
53
|
+
const statusColor =
|
|
54
|
+
f.status === "M"
|
|
55
|
+
? chalk.yellow
|
|
56
|
+
: f.status === "A" || f.status === "??"
|
|
57
|
+
? chalk.green
|
|
58
|
+
: f.status === "D"
|
|
59
|
+
? chalk.red
|
|
60
|
+
: chalk.white;
|
|
61
|
+
logger.log(` ${statusColor(f.status.padEnd(3))} ${f.file}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} catch (err) {
|
|
65
|
+
logger.error(`Git status failed: ${err.message}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// git init
|
|
71
|
+
git
|
|
72
|
+
.command("init")
|
|
73
|
+
.description("Initialize a git repository")
|
|
74
|
+
.option("-d, --dir <dir>", "Target directory", ".")
|
|
75
|
+
.action(async (options) => {
|
|
76
|
+
try {
|
|
77
|
+
const dir = resolve(options.dir);
|
|
78
|
+
const result = gitInit(dir);
|
|
79
|
+
if (result.initialized) {
|
|
80
|
+
logger.success(`Initialized git repository in ${chalk.gray(dir)}`);
|
|
81
|
+
} else {
|
|
82
|
+
logger.info(result.message);
|
|
83
|
+
}
|
|
84
|
+
} catch (err) {
|
|
85
|
+
logger.error(`Git init failed: ${err.message}`);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// git auto-commit
|
|
91
|
+
git
|
|
92
|
+
.command("auto-commit")
|
|
93
|
+
.description("Auto-commit all changes with a generated message")
|
|
94
|
+
.option("-d, --dir <dir>", "Target directory", ".")
|
|
95
|
+
.option("-m, --message <msg>", "Custom commit message")
|
|
96
|
+
.option("--json", "Output as JSON")
|
|
97
|
+
.action(async (options) => {
|
|
98
|
+
try {
|
|
99
|
+
const dir = resolve(options.dir);
|
|
100
|
+
const result = gitAutoCommit(dir, options.message);
|
|
101
|
+
|
|
102
|
+
if (options.json) {
|
|
103
|
+
console.log(JSON.stringify(result, null, 2));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!result.committed) {
|
|
108
|
+
logger.info(result.message);
|
|
109
|
+
} else {
|
|
110
|
+
logger.success(
|
|
111
|
+
`Committed ${chalk.cyan(result.hash)}: ${result.message}`,
|
|
112
|
+
);
|
|
113
|
+
logger.log(chalk.gray(` ${result.filesChanged} file(s) changed`));
|
|
114
|
+
}
|
|
115
|
+
} catch (err) {
|
|
116
|
+
logger.error(`Auto-commit failed: ${err.message}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// git hooks
|
|
122
|
+
git
|
|
123
|
+
.command("hooks")
|
|
124
|
+
.description("Install git hooks for the knowledge base")
|
|
125
|
+
.option("-d, --dir <dir>", "Target directory", ".")
|
|
126
|
+
.option("--install", "Install hooks")
|
|
127
|
+
.action(async (options) => {
|
|
128
|
+
try {
|
|
129
|
+
const dir = resolve(options.dir);
|
|
130
|
+
|
|
131
|
+
if (!isGitRepo(dir)) {
|
|
132
|
+
logger.error("Not a git repository. Run 'git init' first.");
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (options.install) {
|
|
137
|
+
const { installHooks } = await import("../lib/git-integration.js");
|
|
138
|
+
const result = installHooks(dir);
|
|
139
|
+
logger.success(
|
|
140
|
+
`Installed ${chalk.cyan(result.hook)} hook at ${chalk.gray(result.path)}`,
|
|
141
|
+
);
|
|
142
|
+
} else {
|
|
143
|
+
logger.info(`Use ${chalk.cyan("--install")} to install git hooks`);
|
|
144
|
+
}
|
|
145
|
+
} catch (err) {
|
|
146
|
+
logger.error(`Hooks failed: ${err.message}`);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// git history-analyze
|
|
152
|
+
git
|
|
153
|
+
.command("history-analyze")
|
|
154
|
+
.description("Analyze repository history and statistics")
|
|
155
|
+
.option("-d, --dir <dir>", "Target directory", ".")
|
|
156
|
+
.option("-n, --limit <n>", "Recent commits to show", "10")
|
|
157
|
+
.option("--json", "Output as JSON")
|
|
158
|
+
.action(async (options) => {
|
|
159
|
+
try {
|
|
160
|
+
const dir = resolve(options.dir);
|
|
161
|
+
|
|
162
|
+
if (!isGitRepo(dir)) {
|
|
163
|
+
logger.error("Not a git repository");
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const analysis = gitHistoryAnalyze(dir);
|
|
168
|
+
const recentLog = gitLog(dir, parseInt(options.limit));
|
|
169
|
+
|
|
170
|
+
if (options.json) {
|
|
171
|
+
console.log(
|
|
172
|
+
JSON.stringify({ ...analysis, recentCommits: recentLog }, null, 2),
|
|
173
|
+
);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
logger.log(chalk.bold("Repository Analysis\n"));
|
|
178
|
+
logger.log(
|
|
179
|
+
` ${chalk.gray("Total commits:")} ${analysis.totalCommits}`,
|
|
180
|
+
);
|
|
181
|
+
logger.log(
|
|
182
|
+
` ${chalk.gray("Tracked files:")} ${analysis.trackedFiles}`,
|
|
183
|
+
);
|
|
184
|
+
if (analysis.firstCommit) {
|
|
185
|
+
logger.log(
|
|
186
|
+
` ${chalk.gray("First commit:")} ${analysis.firstCommit}`,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
if (analysis.lastCommit) {
|
|
190
|
+
logger.log(` ${chalk.gray("Last commit:")} ${analysis.lastCommit}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (analysis.contributors.length > 0) {
|
|
194
|
+
logger.log(chalk.bold("\nContributors:\n"));
|
|
195
|
+
for (const c of analysis.contributors) {
|
|
196
|
+
logger.log(
|
|
197
|
+
` ${chalk.cyan(c.commits.toString().padStart(4))} ${c.author}`,
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (recentLog.length > 0) {
|
|
203
|
+
logger.log(chalk.bold("\nRecent Commits:\n"));
|
|
204
|
+
for (const c of recentLog) {
|
|
205
|
+
logger.log(
|
|
206
|
+
` ${chalk.yellow(c.shortHash)} ${chalk.white(c.subject)} ${chalk.gray(c.date)}`,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
} catch (err) {
|
|
211
|
+
logger.error(`Analysis failed: ${err.message}`);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hierarchical Memory 2.0 commands
|
|
3
|
+
* chainlesschain hmemory store|recall|consolidate|search|stats|share|prune
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import ora from "ora";
|
|
8
|
+
import { logger } from "../lib/logger.js";
|
|
9
|
+
import { bootstrap, shutdown } from "../runtime/bootstrap.js";
|
|
10
|
+
import {
|
|
11
|
+
storeMemory,
|
|
12
|
+
recallMemory,
|
|
13
|
+
consolidateMemory,
|
|
14
|
+
searchEpisodic,
|
|
15
|
+
searchSemantic,
|
|
16
|
+
getMemoryStats,
|
|
17
|
+
shareMemory,
|
|
18
|
+
pruneMemory,
|
|
19
|
+
} from "../lib/hierarchical-memory.js";
|
|
20
|
+
|
|
21
|
+
export function registerHmemoryCommand(program) {
|
|
22
|
+
const hmemory = program
|
|
23
|
+
.command("hmemory")
|
|
24
|
+
.description("Hierarchical Memory 2.0 — four-layer memory system");
|
|
25
|
+
|
|
26
|
+
// hmemory store <content>
|
|
27
|
+
hmemory
|
|
28
|
+
.command("store")
|
|
29
|
+
.description("Store a memory at the appropriate layer")
|
|
30
|
+
.argument("<content>", "Memory content")
|
|
31
|
+
.option("--importance <n>", "Importance 0.0-1.0", "0.5")
|
|
32
|
+
.option("--type <type>", "Memory type (episodic|semantic)", "episodic")
|
|
33
|
+
.option("--core", "Force store as core memory (importance=1.0)")
|
|
34
|
+
.option("--json", "Output as JSON")
|
|
35
|
+
.action(async (content, options) => {
|
|
36
|
+
try {
|
|
37
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
38
|
+
if (!ctx.db) {
|
|
39
|
+
logger.error("Database not available");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
const db = ctx.db.getDatabase();
|
|
43
|
+
const importance = options.core
|
|
44
|
+
? 1.0
|
|
45
|
+
: parseFloat(options.importance) || 0.5;
|
|
46
|
+
const entry = storeMemory(db, content, {
|
|
47
|
+
importance,
|
|
48
|
+
type: options.type,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (options.json) {
|
|
52
|
+
console.log(JSON.stringify(entry, null, 2));
|
|
53
|
+
} else {
|
|
54
|
+
logger.success(
|
|
55
|
+
`Memory stored: ${chalk.gray(entry.id.slice(0, 16))} → ${chalk.cyan(entry.layer)}`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
await shutdown();
|
|
60
|
+
} catch (err) {
|
|
61
|
+
logger.error(`Failed: ${err.message}`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// hmemory recall <query>
|
|
67
|
+
hmemory
|
|
68
|
+
.command("recall")
|
|
69
|
+
.description("Recall memories with forgetting curve")
|
|
70
|
+
.argument("<query>", "Search query")
|
|
71
|
+
.option("-n, --limit <n>", "Max results", "20")
|
|
72
|
+
.option("--json", "Output as JSON")
|
|
73
|
+
.action(async (query, options) => {
|
|
74
|
+
try {
|
|
75
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
76
|
+
if (!ctx.db) {
|
|
77
|
+
logger.error("Database not available");
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
const db = ctx.db.getDatabase();
|
|
81
|
+
const results = recallMemory(db, query, {
|
|
82
|
+
limit: parseInt(options.limit) || 20,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (options.json) {
|
|
86
|
+
console.log(JSON.stringify(results, null, 2));
|
|
87
|
+
} else if (results.length === 0) {
|
|
88
|
+
logger.info(`No memories matching "${query}" above recall threshold`);
|
|
89
|
+
} else {
|
|
90
|
+
logger.log(chalk.bold(`Recalled ${results.length} memories:\n`));
|
|
91
|
+
for (const r of results) {
|
|
92
|
+
const retention = (r.retention * 100).toFixed(0);
|
|
93
|
+
logger.log(
|
|
94
|
+
` ${chalk.gray(r.id.slice(0, 16))} [${chalk.cyan(r.layer)}] retention=${chalk.yellow(retention + "%")}`,
|
|
95
|
+
);
|
|
96
|
+
logger.log(
|
|
97
|
+
` ${chalk.white(r.content.substring(0, 120).replace(/\n/g, " "))}`,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
await shutdown();
|
|
103
|
+
} catch (err) {
|
|
104
|
+
logger.error(`Failed: ${err.message}`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// hmemory consolidate
|
|
110
|
+
hmemory
|
|
111
|
+
.command("consolidate")
|
|
112
|
+
.description("Promote and forget memories across layers")
|
|
113
|
+
.action(async () => {
|
|
114
|
+
try {
|
|
115
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
116
|
+
if (!ctx.db) {
|
|
117
|
+
logger.error("Database not available");
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
const db = ctx.db.getDatabase();
|
|
121
|
+
const spinner = ora("Consolidating memories...").start();
|
|
122
|
+
const result = consolidateMemory(db);
|
|
123
|
+
spinner.succeed(
|
|
124
|
+
`Consolidation complete: ${chalk.green(result.promoted)} promoted, ${chalk.red(result.forgotten)} forgotten`,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
await shutdown();
|
|
128
|
+
} catch (err) {
|
|
129
|
+
logger.error(`Failed: ${err.message}`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// hmemory search <query>
|
|
135
|
+
hmemory
|
|
136
|
+
.command("search")
|
|
137
|
+
.description("Search memories by type")
|
|
138
|
+
.argument("<query>", "Search query")
|
|
139
|
+
.option("--type <type>", "Memory type (episodic|semantic)", "episodic")
|
|
140
|
+
.option("-n, --limit <n>", "Max results", "20")
|
|
141
|
+
.option("--json", "Output as JSON")
|
|
142
|
+
.action(async (query, options) => {
|
|
143
|
+
try {
|
|
144
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
145
|
+
if (!ctx.db) {
|
|
146
|
+
logger.error("Database not available");
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
const db = ctx.db.getDatabase();
|
|
150
|
+
const searchFn =
|
|
151
|
+
options.type === "semantic" ? searchSemantic : searchEpisodic;
|
|
152
|
+
const results = searchFn(db, query, {
|
|
153
|
+
limit: parseInt(options.limit) || 20,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (options.json) {
|
|
157
|
+
console.log(JSON.stringify(results, null, 2));
|
|
158
|
+
} else if (results.length === 0) {
|
|
159
|
+
logger.info(`No ${options.type} memories matching "${query}"`);
|
|
160
|
+
} else {
|
|
161
|
+
logger.log(
|
|
162
|
+
chalk.bold(`${options.type} search (${results.length} results):\n`),
|
|
163
|
+
);
|
|
164
|
+
for (const r of results) {
|
|
165
|
+
logger.log(
|
|
166
|
+
` ${chalk.gray(r.id.slice(0, 16))} [${chalk.cyan(r.layer)}] importance=${chalk.yellow(r.importance)}`,
|
|
167
|
+
);
|
|
168
|
+
logger.log(
|
|
169
|
+
` ${chalk.white(r.content.substring(0, 120).replace(/\n/g, " "))}`,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
await shutdown();
|
|
175
|
+
} catch (err) {
|
|
176
|
+
logger.error(`Failed: ${err.message}`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// hmemory stats
|
|
182
|
+
hmemory
|
|
183
|
+
.command("stats")
|
|
184
|
+
.description("Show memory statistics")
|
|
185
|
+
.option("--json", "Output as JSON")
|
|
186
|
+
.action(async (options) => {
|
|
187
|
+
try {
|
|
188
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
189
|
+
if (!ctx.db) {
|
|
190
|
+
logger.error("Database not available");
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
const db = ctx.db.getDatabase();
|
|
194
|
+
const stats = getMemoryStats(db);
|
|
195
|
+
|
|
196
|
+
if (options.json) {
|
|
197
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
198
|
+
} else {
|
|
199
|
+
logger.log(chalk.bold("Hierarchical Memory Stats:\n"));
|
|
200
|
+
logger.log(` Working: ${chalk.yellow(stats.working)}`);
|
|
201
|
+
logger.log(` Short-term: ${chalk.yellow(stats.shortTerm)}`);
|
|
202
|
+
logger.log(` Long-term: ${chalk.yellow(stats.longTerm)}`);
|
|
203
|
+
logger.log(` Core: ${chalk.yellow(stats.core)}`);
|
|
204
|
+
logger.log(` Shared: ${chalk.yellow(stats.shared)}`);
|
|
205
|
+
logger.log(
|
|
206
|
+
` ${chalk.bold("Total:")} ${chalk.green(stats.total)}`,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
await shutdown();
|
|
211
|
+
} catch (err) {
|
|
212
|
+
logger.error(`Failed: ${err.message}`);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// hmemory share <id> <agent-id>
|
|
218
|
+
hmemory
|
|
219
|
+
.command("share")
|
|
220
|
+
.description("Share a memory with another agent")
|
|
221
|
+
.argument("<id>", "Memory ID")
|
|
222
|
+
.argument("<agent-id>", "Target agent ID")
|
|
223
|
+
.option("--privacy <level>", "Privacy level (full|filtered)", "filtered")
|
|
224
|
+
.option("--json", "Output as JSON")
|
|
225
|
+
.action(async (id, agentId, options) => {
|
|
226
|
+
try {
|
|
227
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
228
|
+
if (!ctx.db) {
|
|
229
|
+
logger.error("Database not available");
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
const db = ctx.db.getDatabase();
|
|
233
|
+
const result = shareMemory(db, id, agentId, options.privacy);
|
|
234
|
+
|
|
235
|
+
if (options.json) {
|
|
236
|
+
console.log(JSON.stringify(result, null, 2));
|
|
237
|
+
} else {
|
|
238
|
+
logger.success(
|
|
239
|
+
`Memory ${chalk.gray(id.slice(0, 16))} shared with ${chalk.cyan(agentId)} [${options.privacy}]`,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
await shutdown();
|
|
244
|
+
} catch (err) {
|
|
245
|
+
logger.error(`Failed: ${err.message}`);
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// hmemory prune
|
|
251
|
+
hmemory
|
|
252
|
+
.command("prune")
|
|
253
|
+
.description("Remove weak old memories")
|
|
254
|
+
.option("--max-age <hours>", "Maximum age in hours", "720")
|
|
255
|
+
.action(async (options) => {
|
|
256
|
+
try {
|
|
257
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
258
|
+
if (!ctx.db) {
|
|
259
|
+
logger.error("Database not available");
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
262
|
+
const db = ctx.db.getDatabase();
|
|
263
|
+
const spinner = ora("Pruning stale memories...").start();
|
|
264
|
+
const result = pruneMemory(db, { maxAge: options.maxAge });
|
|
265
|
+
spinner.succeed(`Pruned ${chalk.red(result.pruned)} stale memories`);
|
|
266
|
+
|
|
267
|
+
await shutdown();
|
|
268
|
+
} catch (err) {
|
|
269
|
+
logger.error(`Failed: ${err.message}`);
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
}
|