@aman_asmuei/aman-agent 0.17.0 → 0.17.1
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/dist/index.js +395 -59
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -878,7 +878,10 @@ import {
|
|
|
878
878
|
consolidateMemories,
|
|
879
879
|
cosineSimilarity,
|
|
880
880
|
preloadEmbeddings,
|
|
881
|
-
buildVectorIndex
|
|
881
|
+
buildVectorIndex,
|
|
882
|
+
recallMemories,
|
|
883
|
+
generateEmbedding,
|
|
884
|
+
getVectorIndex
|
|
882
885
|
} from "@aman_asmuei/amem-core";
|
|
883
886
|
import path5 from "path";
|
|
884
887
|
import os5 from "os";
|
|
@@ -933,7 +936,43 @@ function memoryLog(sessionId, role, content) {
|
|
|
933
936
|
});
|
|
934
937
|
}
|
|
935
938
|
function reminderCheck() {
|
|
936
|
-
|
|
939
|
+
const all = getDb().checkReminders();
|
|
940
|
+
return all.filter((r) => r.scope === "global" || r.scope === currentProject);
|
|
941
|
+
}
|
|
942
|
+
async function memoryForget(opts) {
|
|
943
|
+
const db2 = getDb();
|
|
944
|
+
if (opts.id) {
|
|
945
|
+
const fullId = db2.resolveId(opts.id) ?? opts.id;
|
|
946
|
+
const memory = db2.getById(fullId);
|
|
947
|
+
if (!memory) return { deleted: 0, message: `Memory ${opts.id} not found.` };
|
|
948
|
+
db2.deleteMemory(fullId);
|
|
949
|
+
const vecIdx = getVectorIndex();
|
|
950
|
+
if (vecIdx) vecIdx.remove(fullId);
|
|
951
|
+
return { deleted: 1, message: `Deleted: "${memory.content}" (${memory.type})` };
|
|
952
|
+
}
|
|
953
|
+
if (opts.type) {
|
|
954
|
+
const all = db2.getAllForProject(currentProject);
|
|
955
|
+
const matches = all.filter((m) => m.type === opts.type);
|
|
956
|
+
if (matches.length === 0) return { deleted: 0, message: `No memories of type "${opts.type}" found.` };
|
|
957
|
+
const vecIdx = getVectorIndex();
|
|
958
|
+
for (const m of matches) {
|
|
959
|
+
db2.deleteMemory(m.id);
|
|
960
|
+
if (vecIdx) vecIdx.remove(m.id);
|
|
961
|
+
}
|
|
962
|
+
return { deleted: matches.length, message: `Deleted ${matches.length} "${opts.type}" memories.` };
|
|
963
|
+
}
|
|
964
|
+
if (opts.query) {
|
|
965
|
+
const queryEmbedding = await generateEmbedding(opts.query);
|
|
966
|
+
const matches = recallMemories(db2, { query: opts.query, queryEmbedding, limit: 50, minConfidence: 0, scope: currentProject });
|
|
967
|
+
if (matches.length === 0) return { deleted: 0, message: `No memories found matching "${opts.query}".` };
|
|
968
|
+
const vecIdx = getVectorIndex();
|
|
969
|
+
for (const m of matches) {
|
|
970
|
+
db2.deleteMemory(m.id);
|
|
971
|
+
if (vecIdx) vecIdx.remove(m.id);
|
|
972
|
+
}
|
|
973
|
+
return { deleted: matches.length, message: `Deleted ${matches.length} memories matching "${opts.query}".` };
|
|
974
|
+
}
|
|
975
|
+
return { deleted: 0, message: "Provide an id, type, or query to forget." };
|
|
937
976
|
}
|
|
938
977
|
function memoryConsolidate(dryRun = false) {
|
|
939
978
|
return consolidateMemories(getDb(), cosineSimilarity, {
|
|
@@ -943,6 +982,33 @@ function memoryConsolidate(dryRun = false) {
|
|
|
943
982
|
minAccessCount: 0
|
|
944
983
|
});
|
|
945
984
|
}
|
|
985
|
+
function isMemoryInitialized() {
|
|
986
|
+
return db !== null;
|
|
987
|
+
}
|
|
988
|
+
function memoryStats() {
|
|
989
|
+
return getDb().getStats();
|
|
990
|
+
}
|
|
991
|
+
function memoryExport() {
|
|
992
|
+
return getDb().getAllForProject(currentProject);
|
|
993
|
+
}
|
|
994
|
+
function memorySince(hours) {
|
|
995
|
+
const since = Date.now() - hours * 60 * 60 * 1e3;
|
|
996
|
+
const all = getDb().getMemoriesSince(since);
|
|
997
|
+
return all.filter((m) => m.scope === "global" || m.scope === currentProject);
|
|
998
|
+
}
|
|
999
|
+
function memorySearch(query, limit) {
|
|
1000
|
+
return getDb().fullTextSearch(query, limit, currentProject);
|
|
1001
|
+
}
|
|
1002
|
+
function reminderSet(content, dueAt) {
|
|
1003
|
+
return getDb().insertReminder(content, dueAt ?? null, currentProject);
|
|
1004
|
+
}
|
|
1005
|
+
function reminderList(includeCompleted) {
|
|
1006
|
+
return getDb().listReminders(includeCompleted, currentProject);
|
|
1007
|
+
}
|
|
1008
|
+
function reminderComplete(id) {
|
|
1009
|
+
const fullId = getDb().resolveReminderId(id) ?? id;
|
|
1010
|
+
return getDb().completeReminder(fullId);
|
|
1011
|
+
}
|
|
946
1012
|
|
|
947
1013
|
// src/profile-templates.ts
|
|
948
1014
|
import fs6 from "fs";
|
|
@@ -1664,7 +1730,8 @@ function parseCommand(input) {
|
|
|
1664
1730
|
const trimmed = input.trim();
|
|
1665
1731
|
const parts = trimmed.split(/\s+/);
|
|
1666
1732
|
const base = parts[0].toLowerCase().replace(/^\//, "");
|
|
1667
|
-
|
|
1733
|
+
let action = parts.length > 1 ? parts[1].toLowerCase() : void 0;
|
|
1734
|
+
if (action === "--help" || action === "-h") action = "help";
|
|
1668
1735
|
const args = parts.slice(2);
|
|
1669
1736
|
return { base, action, args };
|
|
1670
1737
|
}
|
|
@@ -1702,7 +1769,14 @@ async function handleIdentityCommand(action, args, ctx) {
|
|
|
1702
1769
|
const output = await mcpWrite(ctx, "identity", "identity_update_section", { section, content });
|
|
1703
1770
|
return { handled: true, output };
|
|
1704
1771
|
}
|
|
1705
|
-
|
|
1772
|
+
if (action === "help") {
|
|
1773
|
+
return { handled: true, output: [
|
|
1774
|
+
pc3.bold("Identity commands:"),
|
|
1775
|
+
` ${pc3.cyan("/identity")} View current identity`,
|
|
1776
|
+
` ${pc3.cyan("/identity update")} <section> Update a section`
|
|
1777
|
+
].join("\n") };
|
|
1778
|
+
}
|
|
1779
|
+
return { handled: true, output: pc3.yellow(`Unknown action: /identity ${action}. Try /identity --help`) };
|
|
1706
1780
|
}
|
|
1707
1781
|
async function handleRulesCommand(action, args, ctx) {
|
|
1708
1782
|
const home2 = os9.homedir();
|
|
@@ -1733,7 +1807,16 @@ async function handleRulesCommand(action, args, ctx) {
|
|
|
1733
1807
|
const output = await mcpWrite(ctx, "rules", "rules_toggle", { category: args[0], index: parseInt(args[1], 10) });
|
|
1734
1808
|
return { handled: true, output };
|
|
1735
1809
|
}
|
|
1736
|
-
|
|
1810
|
+
if (action === "help") {
|
|
1811
|
+
return { handled: true, output: [
|
|
1812
|
+
pc3.bold("Rules commands:"),
|
|
1813
|
+
` ${pc3.cyan("/rules")} View current rules`,
|
|
1814
|
+
` ${pc3.cyan("/rules add")} <category> <text> Add a rule`,
|
|
1815
|
+
` ${pc3.cyan("/rules remove")} <category> <idx> Remove a rule`,
|
|
1816
|
+
` ${pc3.cyan("/rules toggle")} <category> <idx> Toggle a rule`
|
|
1817
|
+
].join("\n") };
|
|
1818
|
+
}
|
|
1819
|
+
return { handled: true, output: pc3.yellow(`Unknown action: /rules ${action}. Try /rules --help`) };
|
|
1737
1820
|
}
|
|
1738
1821
|
async function handleWorkflowsCommand(action, args, ctx) {
|
|
1739
1822
|
const home2 = os9.homedir();
|
|
@@ -1755,7 +1838,15 @@ async function handleWorkflowsCommand(action, args, ctx) {
|
|
|
1755
1838
|
const output = await mcpWrite(ctx, "workflows", "workflow_remove", { name: args.join(" ") });
|
|
1756
1839
|
return { handled: true, output };
|
|
1757
1840
|
}
|
|
1758
|
-
|
|
1841
|
+
if (action === "help") {
|
|
1842
|
+
return { handled: true, output: [
|
|
1843
|
+
pc3.bold("Workflow commands:"),
|
|
1844
|
+
` ${pc3.cyan("/workflows")} View current workflows`,
|
|
1845
|
+
` ${pc3.cyan("/workflows add")} <name> Add a workflow`,
|
|
1846
|
+
` ${pc3.cyan("/workflows remove")} <name> Remove a workflow`
|
|
1847
|
+
].join("\n") };
|
|
1848
|
+
}
|
|
1849
|
+
return { handled: true, output: pc3.yellow(`Unknown action: /workflows ${action}. Try /workflows --help`) };
|
|
1759
1850
|
}
|
|
1760
1851
|
var AKIT_REGISTRY = [
|
|
1761
1852
|
{ name: "web-search", description: "Search the web for current information", category: "search", mcp: { package: "@anthropic/web-search", command: "npx", args: ["-y", "@anthropic/web-search"] } },
|
|
@@ -1977,7 +2068,15 @@ async function handleSkillsCommand(action, args, ctx) {
|
|
|
1977
2068
|
const output = await mcpWrite(ctx, "skills", "skill_uninstall", { name: args.join(" ") });
|
|
1978
2069
|
return { handled: true, output };
|
|
1979
2070
|
}
|
|
1980
|
-
|
|
2071
|
+
if (action === "help") {
|
|
2072
|
+
return { handled: true, output: [
|
|
2073
|
+
pc3.bold("Skills commands:"),
|
|
2074
|
+
` ${pc3.cyan("/skills")} View installed skills`,
|
|
2075
|
+
` ${pc3.cyan("/skills install")} <name> Install a skill`,
|
|
2076
|
+
` ${pc3.cyan("/skills uninstall")} <name> Uninstall a skill`
|
|
2077
|
+
].join("\n") };
|
|
2078
|
+
}
|
|
2079
|
+
return { handled: true, output: pc3.yellow(`Unknown action: /skills ${action}. Try /skills --help`) };
|
|
1981
2080
|
}
|
|
1982
2081
|
async function handleEvalCommand(action, args, ctx) {
|
|
1983
2082
|
const home2 = os9.homedir();
|
|
@@ -2007,7 +2106,7 @@ async function handleMemoryCommand(action, args, ctx) {
|
|
|
2007
2106
|
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2008
2107
|
}
|
|
2009
2108
|
}
|
|
2010
|
-
if (action && !["search", "clear", "timeline"].includes(action)) {
|
|
2109
|
+
if (action && !["search", "clear", "timeline", "stats", "export", "since", "fts", "help"].includes(action)) {
|
|
2011
2110
|
try {
|
|
2012
2111
|
const topic = [action, ...args].join(" ");
|
|
2013
2112
|
const result = await memoryContext(topic);
|
|
@@ -2033,10 +2132,18 @@ async function handleMemoryCommand(action, args, ctx) {
|
|
|
2033
2132
|
}
|
|
2034
2133
|
if (action === "clear") {
|
|
2035
2134
|
if (args.length < 1) {
|
|
2036
|
-
return { handled: true, output: pc3.yellow("Usage: /memory clear <
|
|
2135
|
+
return { handled: true, output: pc3.yellow("Usage: /memory clear <query> \u2014 delete memories matching a search query\n /memory clear --type <type> \u2014 delete all memories of a type (correction|decision|pattern|preference|topology|fact)") };
|
|
2136
|
+
}
|
|
2137
|
+
try {
|
|
2138
|
+
if (args[0] === "--type" && args[1]) {
|
|
2139
|
+
const result2 = await memoryForget({ query: args[1], type: args[1] });
|
|
2140
|
+
return { handled: true, output: result2.deleted > 0 ? pc3.green(result2.message) : pc3.dim(result2.message) };
|
|
2141
|
+
}
|
|
2142
|
+
const result = await memoryForget({ query: args.join(" ") });
|
|
2143
|
+
return { handled: true, output: result.deleted > 0 ? pc3.green(result.message) : pc3.dim(result.message) };
|
|
2144
|
+
} catch (err) {
|
|
2145
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2037
2146
|
}
|
|
2038
|
-
const output = await mcpWrite(ctx, "memory", "memory_forget", { category: args[0] });
|
|
2039
|
-
return { handled: true, output };
|
|
2040
2147
|
}
|
|
2041
2148
|
if (action === "timeline") {
|
|
2042
2149
|
try {
|
|
@@ -2082,11 +2189,115 @@ async function handleMemoryCommand(action, args, ctx) {
|
|
|
2082
2189
|
return { handled: true, output: pc3.red("Failed to retrieve memory timeline.") };
|
|
2083
2190
|
}
|
|
2084
2191
|
}
|
|
2085
|
-
|
|
2192
|
+
if (action === "stats") {
|
|
2193
|
+
try {
|
|
2194
|
+
const stats = memoryStats();
|
|
2195
|
+
const lines = [pc3.bold("Memory Statistics:"), ""];
|
|
2196
|
+
lines.push(` Total memories: ${pc3.bold(String(stats.total))}`);
|
|
2197
|
+
if (Object.keys(stats.byType).length > 0) {
|
|
2198
|
+
lines.push("");
|
|
2199
|
+
lines.push(` ${pc3.dim("By type:")}`);
|
|
2200
|
+
for (const [type, count] of Object.entries(stats.byType)) {
|
|
2201
|
+
lines.push(` ${type.padEnd(16)} ${count}`);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
return { handled: true, output: lines.join("\n") };
|
|
2205
|
+
} catch (err) {
|
|
2206
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
if (action === "export") {
|
|
2210
|
+
try {
|
|
2211
|
+
const format = args[0] === "json" ? "json" : "markdown";
|
|
2212
|
+
const memories = memoryExport();
|
|
2213
|
+
if (memories.length === 0) {
|
|
2214
|
+
return { handled: true, output: pc3.dim("No memories to export.") };
|
|
2215
|
+
}
|
|
2216
|
+
if (format === "json") {
|
|
2217
|
+
const jsonOut = memories.map((m) => ({ id: m.id, type: m.type, content: m.content, tags: m.tags, confidence: m.confidence, createdAt: m.createdAt, tier: m.tier }));
|
|
2218
|
+
return { handled: true, output: JSON.stringify(jsonOut, null, 2) };
|
|
2219
|
+
}
|
|
2220
|
+
const lines = [`# Memory Export (${memories.length} memories)`, ""];
|
|
2221
|
+
for (const m of memories) {
|
|
2222
|
+
const date = new Date(m.createdAt).toLocaleDateString();
|
|
2223
|
+
const tags = m.tags.length > 0 ? ` [${m.tags.map((t) => `#${t}`).join(", ")}]` : "";
|
|
2224
|
+
lines.push(`- **[${m.type}]** ${m.content}${tags} ${pc3.dim(`(${date}, ${Math.round(m.confidence * 100)}%)`)}`);
|
|
2225
|
+
}
|
|
2226
|
+
return { handled: true, output: lines.join("\n") };
|
|
2227
|
+
} catch (err) {
|
|
2228
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
if (action === "since") {
|
|
2232
|
+
try {
|
|
2233
|
+
let hours = 24;
|
|
2234
|
+
if (args[0]) {
|
|
2235
|
+
const match = args[0].match(/^(\d+)(h|d|w)$/);
|
|
2236
|
+
if (match) {
|
|
2237
|
+
const value = parseInt(match[1], 10);
|
|
2238
|
+
const unit = match[2];
|
|
2239
|
+
if (unit === "h") hours = value;
|
|
2240
|
+
else if (unit === "d") hours = value * 24;
|
|
2241
|
+
else if (unit === "w") hours = value * 24 * 7;
|
|
2242
|
+
} else {
|
|
2243
|
+
return { handled: true, output: pc3.yellow("Usage: /memory since <Nh|Nd|Nw> (e.g., 24h, 7d, 1w)") };
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
const memories = memorySince(hours);
|
|
2247
|
+
if (memories.length === 0) {
|
|
2248
|
+
return { handled: true, output: pc3.dim(`No memories in the last ${args[0] || "24h"}.`) };
|
|
2249
|
+
}
|
|
2250
|
+
const lines = [pc3.bold(`Memories since ${args[0] || "24h"} (${memories.length}):`), ""];
|
|
2251
|
+
for (const m of memories) {
|
|
2252
|
+
const age = Math.round((Date.now() - m.createdAt) / 36e5);
|
|
2253
|
+
const ageStr = age < 1 ? "<1h ago" : `${age}h ago`;
|
|
2254
|
+
lines.push(` ${pc3.dim(ageStr.padEnd(10))} [${m.type}] ${m.content}`);
|
|
2255
|
+
}
|
|
2256
|
+
return { handled: true, output: lines.join("\n") };
|
|
2257
|
+
} catch (err) {
|
|
2258
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
if (action === "fts") {
|
|
2262
|
+
if (args.length < 1) {
|
|
2263
|
+
return { handled: true, output: pc3.yellow("Usage: /memory fts <query...> \u2014 full-text search") };
|
|
2264
|
+
}
|
|
2265
|
+
try {
|
|
2266
|
+
const query = args.join(" ");
|
|
2267
|
+
const results = memorySearch(query, 20);
|
|
2268
|
+
if (results.length === 0) {
|
|
2269
|
+
return { handled: true, output: pc3.dim(`No results for full-text search: "${query}".`) };
|
|
2270
|
+
}
|
|
2271
|
+
const lines = [pc3.bold(`FTS results for "${query}" (${results.length}):`), ""];
|
|
2272
|
+
for (const m of results) {
|
|
2273
|
+
const tags = m.tags.length > 0 ? ` ${pc3.dim(m.tags.map((t) => `#${t}`).join(" "))}` : "";
|
|
2274
|
+
lines.push(` [${m.type}] ${m.content}${tags}`);
|
|
2275
|
+
}
|
|
2276
|
+
return { handled: true, output: lines.join("\n") };
|
|
2277
|
+
} catch (err) {
|
|
2278
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
if (action === "help") {
|
|
2282
|
+
return { handled: true, output: [
|
|
2283
|
+
pc3.bold("Memory commands:"),
|
|
2284
|
+
` ${pc3.cyan("/memory")} View recent context`,
|
|
2285
|
+
` ${pc3.cyan("/memory")} <topic> Context for a topic`,
|
|
2286
|
+
` ${pc3.cyan("/memory search")} <query> Search memories (semantic)`,
|
|
2287
|
+
` ${pc3.cyan("/memory fts")} <query> Full-text search (FTS5)`,
|
|
2288
|
+
` ${pc3.cyan("/memory since")} <Nh|Nd|Nw> Memories from time window`,
|
|
2289
|
+
` ${pc3.cyan("/memory stats")} Show memory statistics`,
|
|
2290
|
+
` ${pc3.cyan("/memory export")} [json] Export all memories`,
|
|
2291
|
+
` ${pc3.cyan("/memory timeline")} View memory timeline`,
|
|
2292
|
+
` ${pc3.cyan("/memory clear")} <query> Delete matching memories`,
|
|
2293
|
+
` ${pc3.cyan("/memory clear --type")} <type> Delete all of a type`
|
|
2294
|
+
].join("\n") };
|
|
2295
|
+
}
|
|
2296
|
+
return { handled: true, output: pc3.yellow(`Unknown action: /memory ${action}. Try /memory --help`) };
|
|
2086
2297
|
}
|
|
2087
2298
|
function handleStatusCommand(ctx) {
|
|
2088
2299
|
const mcpToolCount = ctx.mcpManager ? ctx.mcpManager.getTools().length : 0;
|
|
2089
|
-
const amemConnected =
|
|
2300
|
+
const amemConnected = isMemoryInitialized();
|
|
2090
2301
|
const status = getEcosystemStatus(mcpToolCount, amemConnected);
|
|
2091
2302
|
const lines = [pc3.bold("Aman Ecosystem Dashboard"), ""];
|
|
2092
2303
|
for (const layer of status.layers) {
|
|
@@ -2102,7 +2313,7 @@ function handleStatusCommand(ctx) {
|
|
|
2102
2313
|
}
|
|
2103
2314
|
function handleDoctorCommand(ctx) {
|
|
2104
2315
|
const mcpToolCount = ctx.mcpManager ? ctx.mcpManager.getTools().length : 0;
|
|
2105
|
-
const amemConnected =
|
|
2316
|
+
const amemConnected = isMemoryInitialized();
|
|
2106
2317
|
const status = getEcosystemStatus(mcpToolCount, amemConnected);
|
|
2107
2318
|
const lines = [pc3.bold("Aman Health Check"), ""];
|
|
2108
2319
|
let healthy = 0;
|
|
@@ -2136,7 +2347,7 @@ function handleDoctorCommand(ctx) {
|
|
|
2136
2347
|
}
|
|
2137
2348
|
lines.push(` ${status.amemConnected ? pc3.green("\u2713") : pc3.red("\u2717")} ${"Memory".padEnd(12)} ${status.amemConnected ? pc3.green("connected") : pc3.red("not connected")}`);
|
|
2138
2349
|
if (!status.amemConnected) {
|
|
2139
|
-
lines.push(` ${pc3.dim("\u2192 Fix:
|
|
2350
|
+
lines.push(` ${pc3.dim("\u2192 Fix: restart aman-agent (memory initializes automatically)")}`);
|
|
2140
2351
|
fixes++;
|
|
2141
2352
|
} else {
|
|
2142
2353
|
healthy++;
|
|
@@ -2158,7 +2369,8 @@ function handleHelp() {
|
|
|
2158
2369
|
` ${pc3.cyan("/akit")} Manage tools [add|remove <tool>]`,
|
|
2159
2370
|
` ${pc3.cyan("/skills")} View skills [install|uninstall ...]`,
|
|
2160
2371
|
` ${pc3.cyan("/eval")} View evaluation [milestone ...]`,
|
|
2161
|
-
` ${pc3.cyan("/memory")} View recent memories [search|clear|timeline]`,
|
|
2372
|
+
` ${pc3.cyan("/memory")} View recent memories [search|fts|since|stats|export|clear|timeline]`,
|
|
2373
|
+
` ${pc3.cyan("/reminder")} Manage reminders [set|check|done]`,
|
|
2162
2374
|
` ${pc3.cyan("/status")} Ecosystem dashboard`,
|
|
2163
2375
|
` ${pc3.cyan("/doctor")} Health check all layers`,
|
|
2164
2376
|
` ${pc3.cyan("/decisions")} View decision log [<project>]`,
|
|
@@ -2167,7 +2379,7 @@ function handleHelp() {
|
|
|
2167
2379
|
` ${pc3.cyan("/save")} Save conversation to memory`,
|
|
2168
2380
|
` ${pc3.cyan("/model")} Show current LLM model`,
|
|
2169
2381
|
` ${pc3.cyan("/update")} Check for updates`,
|
|
2170
|
-
` ${pc3.cyan("/
|
|
2382
|
+
` ${pc3.cyan("/reset")} Full reset [all|memory|config|identity|rules]`,
|
|
2171
2383
|
` ${pc3.cyan("/clear")} Clear conversation history`,
|
|
2172
2384
|
` ${pc3.cyan("/quit")} Exit`
|
|
2173
2385
|
].join("\n")
|
|
@@ -2176,20 +2388,55 @@ function handleHelp() {
|
|
|
2176
2388
|
function handleSave() {
|
|
2177
2389
|
return { handled: true, saveConversation: true };
|
|
2178
2390
|
}
|
|
2179
|
-
function
|
|
2180
|
-
const
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2391
|
+
function handleReset(action) {
|
|
2392
|
+
const dirs = {
|
|
2393
|
+
config: path9.join(os9.homedir(), ".aman-agent"),
|
|
2394
|
+
memory: path9.join(os9.homedir(), ".amem"),
|
|
2395
|
+
identity: path9.join(os9.homedir(), ".acore"),
|
|
2396
|
+
rules: path9.join(os9.homedir(), ".arules")
|
|
2397
|
+
};
|
|
2398
|
+
if (action === "help" || !action) {
|
|
2399
|
+
return {
|
|
2400
|
+
handled: true,
|
|
2401
|
+
output: [
|
|
2402
|
+
pc3.bold("Reset options:"),
|
|
2403
|
+
` ${pc3.cyan("/reset all")} Full reset \u2014 config, memory, identity, rules`,
|
|
2404
|
+
` ${pc3.cyan("/reset memory")} Clear all memories only`,
|
|
2405
|
+
` ${pc3.cyan("/reset config")} Reset LLM config only`,
|
|
2406
|
+
` ${pc3.cyan("/reset identity")} Reset persona/identity only`,
|
|
2407
|
+
` ${pc3.cyan("/reset rules")} Reset guardrails only`,
|
|
2408
|
+
"",
|
|
2409
|
+
pc3.dim("Directories:"),
|
|
2410
|
+
...Object.entries(dirs).map(([k, v]) => ` ${k}: ${pc3.dim(v)}`)
|
|
2411
|
+
].join("\n")
|
|
2412
|
+
};
|
|
2413
|
+
}
|
|
2414
|
+
const targets = action === "all" ? ["config", "memory", "identity", "rules"] : [action];
|
|
2415
|
+
if (!targets.every((t) => t in dirs)) {
|
|
2416
|
+
return { handled: true, output: pc3.red(`Unknown target: ${action}. Use /reset help`) };
|
|
2417
|
+
}
|
|
2418
|
+
const removed = [];
|
|
2419
|
+
for (const target of targets) {
|
|
2420
|
+
const dir = dirs[target];
|
|
2421
|
+
if (fs9.existsSync(dir)) {
|
|
2422
|
+
fs9.rmSync(dir, { recursive: true, force: true });
|
|
2423
|
+
removed.push(target);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
if (targets.includes("config")) {
|
|
2427
|
+
const configDir = dirs.config;
|
|
2428
|
+
fs9.mkdirSync(configDir, { recursive: true });
|
|
2429
|
+
fs9.writeFileSync(path9.join(configDir, ".reconfig"), "", "utf-8");
|
|
2430
|
+
}
|
|
2431
|
+
if (removed.length === 0) {
|
|
2432
|
+
return { handled: true, output: pc3.dim("Nothing to reset \u2014 directories don't exist.") };
|
|
2184
2433
|
}
|
|
2185
|
-
fs9.mkdirSync(configDir, { recursive: true });
|
|
2186
|
-
fs9.writeFileSync(path9.join(configDir, ".reconfig"), "", "utf-8");
|
|
2187
2434
|
return {
|
|
2188
2435
|
handled: true,
|
|
2189
2436
|
quit: true,
|
|
2190
2437
|
output: [
|
|
2191
|
-
pc3.green(
|
|
2192
|
-
"
|
|
2438
|
+
pc3.green(`Reset complete: ${removed.join(", ")}`),
|
|
2439
|
+
"Restart aman-agent to begin fresh."
|
|
2193
2440
|
].join("\n")
|
|
2194
2441
|
};
|
|
2195
2442
|
}
|
|
@@ -2634,6 +2881,86 @@ function handlePlanCommand(action, args) {
|
|
|
2634
2881
|
return { handled: true, output: pc3.yellow(`Unknown plan action: ${action}. Try /plan help`) };
|
|
2635
2882
|
}
|
|
2636
2883
|
}
|
|
2884
|
+
async function handleReminderCommand(action, args) {
|
|
2885
|
+
if (!action || action === "list") {
|
|
2886
|
+
try {
|
|
2887
|
+
const reminders = reminderList();
|
|
2888
|
+
if (reminders.length === 0) return { handled: true, output: pc3.dim("No reminders.") };
|
|
2889
|
+
const lines = [pc3.bold(`Reminders (${reminders.length}):`), ""];
|
|
2890
|
+
for (const r of reminders) {
|
|
2891
|
+
const status = r.completed ? pc3.green("[done]") : pc3.yellow("[todo]");
|
|
2892
|
+
const due = r.dueAt ? ` ${pc3.dim(`due: ${new Date(r.dueAt).toLocaleString()}`)}` : "";
|
|
2893
|
+
lines.push(` ${status} ${r.content}${due} ${pc3.dim(`(${r.id.slice(0, 8)})`)}`);
|
|
2894
|
+
}
|
|
2895
|
+
return { handled: true, output: lines.join("\n") };
|
|
2896
|
+
} catch (err) {
|
|
2897
|
+
return { handled: true, output: pc3.red(`Reminder error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
if (action === "set" || action === "add") {
|
|
2901
|
+
if (args.length === 0) return { handled: true, output: pc3.yellow("Usage: /reminder set <text> [--due <time>]\n Time formats: 1h, 2d, 1w, or ISO date (2026-04-10)") };
|
|
2902
|
+
let dueAt;
|
|
2903
|
+
const dueIdx = args.indexOf("--due");
|
|
2904
|
+
let contentArgs = args;
|
|
2905
|
+
if (dueIdx >= 0 && args[dueIdx + 1]) {
|
|
2906
|
+
const dueStr = args[dueIdx + 1];
|
|
2907
|
+
contentArgs = [...args.slice(0, dueIdx), ...args.slice(dueIdx + 2)];
|
|
2908
|
+
const relMatch = dueStr.match(/^(\d+)(h|d|w)$/);
|
|
2909
|
+
if (relMatch) {
|
|
2910
|
+
const num = parseInt(relMatch[1], 10);
|
|
2911
|
+
const unit = relMatch[2];
|
|
2912
|
+
const ms = unit === "h" ? num * 36e5 : unit === "d" ? num * 864e5 : num * 6048e5;
|
|
2913
|
+
dueAt = Date.now() + ms;
|
|
2914
|
+
} else {
|
|
2915
|
+
const parsed = Date.parse(dueStr);
|
|
2916
|
+
if (!isNaN(parsed)) dueAt = parsed;
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
const content = contentArgs.join(" ");
|
|
2920
|
+
if (!content) return { handled: true, output: pc3.yellow("Usage: /reminder set <text> [--due <time>]") };
|
|
2921
|
+
try {
|
|
2922
|
+
const id = reminderSet(content, dueAt);
|
|
2923
|
+
const dueInfo = dueAt ? ` (due: ${new Date(dueAt).toLocaleDateString()})` : "";
|
|
2924
|
+
return { handled: true, output: pc3.green(`Reminder set: "${content}"${dueInfo} (ID: ${id.slice(0, 8)})`) };
|
|
2925
|
+
} catch (err) {
|
|
2926
|
+
return { handled: true, output: pc3.red(`Reminder error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
if (action === "done" || action === "complete") {
|
|
2930
|
+
if (!args[0]) return { handled: true, output: pc3.yellow("Usage: /reminder done <id>") };
|
|
2931
|
+
try {
|
|
2932
|
+
const result = reminderComplete(args[0]);
|
|
2933
|
+
return { handled: true, output: result ? pc3.green("Reminder completed.") : pc3.yellow("Reminder not found.") };
|
|
2934
|
+
} catch (err) {
|
|
2935
|
+
return { handled: true, output: pc3.red(`Reminder error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
if (action === "check") {
|
|
2939
|
+
try {
|
|
2940
|
+
const reminders = reminderCheck();
|
|
2941
|
+
if (reminders.length === 0) return { handled: true, output: pc3.dim("No pending reminders.") };
|
|
2942
|
+
const lines = [pc3.bold("Pending Reminders:"), ""];
|
|
2943
|
+
for (const r of reminders) {
|
|
2944
|
+
const icon = r.status === "overdue" ? pc3.red("!!!") : r.status === "today" ? pc3.yellow("(!)") : pc3.dim("( )");
|
|
2945
|
+
const due = r.dueAt ? ` ${pc3.dim(`due: ${new Date(r.dueAt).toLocaleString()}`)}` : "";
|
|
2946
|
+
lines.push(` ${icon} ${r.content}${due} ${pc3.dim(`[${r.status}]`)}`);
|
|
2947
|
+
}
|
|
2948
|
+
return { handled: true, output: lines.join("\n") };
|
|
2949
|
+
} catch (err) {
|
|
2950
|
+
return { handled: true, output: pc3.red(`Reminder error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
if (action === "help") {
|
|
2954
|
+
return { handled: true, output: [
|
|
2955
|
+
pc3.bold("Reminder commands:"),
|
|
2956
|
+
` ${pc3.cyan("/reminder")} List all reminders`,
|
|
2957
|
+
` ${pc3.cyan("/reminder set")} <text> Create a reminder [--due 1h|2d|1w|date]`,
|
|
2958
|
+
` ${pc3.cyan("/reminder check")} Show overdue/upcoming`,
|
|
2959
|
+
` ${pc3.cyan("/reminder done")} <id> Mark as completed`
|
|
2960
|
+
].join("\n") };
|
|
2961
|
+
}
|
|
2962
|
+
return { handled: true, output: pc3.yellow(`Unknown action: /reminder ${action}. Try /reminder --help`) };
|
|
2963
|
+
}
|
|
2637
2964
|
var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
2638
2965
|
"quit",
|
|
2639
2966
|
"exit",
|
|
@@ -2655,8 +2982,8 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
2655
2982
|
"decisions",
|
|
2656
2983
|
"export",
|
|
2657
2984
|
"debug",
|
|
2658
|
-
"
|
|
2659
|
-
"
|
|
2985
|
+
"reset",
|
|
2986
|
+
"reminder",
|
|
2660
2987
|
"update",
|
|
2661
2988
|
"upgrade",
|
|
2662
2989
|
"plan",
|
|
@@ -2707,9 +3034,8 @@ async function handleCommand(input, ctx) {
|
|
|
2707
3034
|
return handleExportCommand();
|
|
2708
3035
|
case "debug":
|
|
2709
3036
|
return handleDebugCommand();
|
|
2710
|
-
case "
|
|
2711
|
-
|
|
2712
|
-
return handleReconfig();
|
|
3037
|
+
case "reset":
|
|
3038
|
+
return handleReset(action);
|
|
2713
3039
|
case "plan":
|
|
2714
3040
|
return handlePlanCommand(action, args);
|
|
2715
3041
|
case "profile":
|
|
@@ -2718,6 +3044,8 @@ async function handleCommand(input, ctx) {
|
|
|
2718
3044
|
return handleDelegateCommand(action, args, ctx);
|
|
2719
3045
|
case "team":
|
|
2720
3046
|
return handleTeamCommand(action, args, ctx);
|
|
3047
|
+
case "reminder":
|
|
3048
|
+
return handleReminderCommand(action, args);
|
|
2721
3049
|
case "update":
|
|
2722
3050
|
case "upgrade":
|
|
2723
3051
|
return handleUpdate();
|
|
@@ -2933,14 +3261,18 @@ async function onSessionStart(ctx) {
|
|
|
2933
3261
|
let firstRun = false;
|
|
2934
3262
|
let resumeTopic;
|
|
2935
3263
|
const visibleReminders = [];
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
3264
|
+
if (!isMemoryInitialized()) {
|
|
3265
|
+
firstRun = false;
|
|
3266
|
+
} else {
|
|
3267
|
+
try {
|
|
3268
|
+
isHookCall = true;
|
|
3269
|
+
const recallResult = await memoryRecall("*", { limit: 1 });
|
|
3270
|
+
firstRun = recallResult.total === 0;
|
|
3271
|
+
} catch {
|
|
3272
|
+
firstRun = true;
|
|
3273
|
+
} finally {
|
|
3274
|
+
isHookCall = false;
|
|
3275
|
+
}
|
|
2944
3276
|
}
|
|
2945
3277
|
if (firstRun) {
|
|
2946
3278
|
contextInjection = `<first-session>
|
|
@@ -3914,7 +4246,7 @@ var BackgroundTaskManager = class {
|
|
|
3914
4246
|
// src/errors.ts
|
|
3915
4247
|
var ERROR_MAPPINGS = [
|
|
3916
4248
|
{ pattern: /rate.?limit|429/i, message: "Rate limited. I'll retry automatically." },
|
|
3917
|
-
{ pattern: /401|unauthorized/i, message: "API key invalid. Run /
|
|
4249
|
+
{ pattern: /401|unauthorized/i, message: "API key invalid. Run /reset config to fix." },
|
|
3918
4250
|
{ pattern: /403|forbidden/i, message: "API key doesn't have access to this model. Try a different model with --model." },
|
|
3919
4251
|
{ pattern: /fetch failed|network/i, message: "Network error. Check your internet connection." },
|
|
3920
4252
|
{ pattern: /ECONNREFUSED/i, message: "Can't reach the API. Are you behind a proxy or firewall?" },
|
|
@@ -4799,7 +5131,7 @@ function bootstrapEcosystem() {
|
|
|
4799
5131
|
return true;
|
|
4800
5132
|
}
|
|
4801
5133
|
var program = new Command();
|
|
4802
|
-
program.name("aman-agent").description("Your AI companion, running locally").version("0.1
|
|
5134
|
+
program.name("aman-agent").description("Your AI companion, running locally").version("0.17.1").option("--model <model>", "Override LLM model").option("--budget <tokens>", "Token budget for system prompt (default: 8000)", parseInt).option("--profile <name>", "Use a specific agent profile (e.g., coder, writer, researcher)").action(async (options) => {
|
|
4803
5135
|
p2.intro(pc7.bold("aman agent") + pc7.dim(" \u2014 your AI companion"));
|
|
4804
5136
|
let config = loadConfig();
|
|
4805
5137
|
if (!config) {
|
|
@@ -4808,7 +5140,7 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
4808
5140
|
config = detected;
|
|
4809
5141
|
const providerLabel = detected.provider === "anthropic" ? "Anthropic API key" : detected.provider === "openai" ? "OpenAI API key" : "Ollama";
|
|
4810
5142
|
p2.log.success(`Auto-detected ${providerLabel}. Using ${pc7.bold(detected.model)}.`);
|
|
4811
|
-
p2.log.info(pc7.dim("Change anytime with /
|
|
5143
|
+
p2.log.info(pc7.dim("Change anytime with /reset config"));
|
|
4812
5144
|
saveConfig(config);
|
|
4813
5145
|
} else {
|
|
4814
5146
|
p2.log.info("First-time setup \u2014 configure your LLM connection.");
|
|
@@ -4926,7 +5258,26 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
4926
5258
|
}
|
|
4927
5259
|
}
|
|
4928
5260
|
const aiName = getProfileAiName(profile);
|
|
4929
|
-
|
|
5261
|
+
try {
|
|
5262
|
+
await initMemory();
|
|
5263
|
+
} catch (err) {
|
|
5264
|
+
p2.log.warning(`Memory initialization failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
5265
|
+
}
|
|
5266
|
+
if (isMemoryInitialized()) {
|
|
5267
|
+
const memSpinner = p2.spinner();
|
|
5268
|
+
memSpinner.start("Consolidating memory");
|
|
5269
|
+
try {
|
|
5270
|
+
const report = memoryConsolidate();
|
|
5271
|
+
memSpinner.stop("Memory consolidated");
|
|
5272
|
+
if (report.merged > 0 || report.pruned > 0 || report.promoted > 0) {
|
|
5273
|
+
p2.log.info(
|
|
5274
|
+
`Memory health: ${report.healthScore ?? "?"}% ` + pc7.dim(`(merged ${report.merged}, pruned ${report.pruned}, promoted ${report.promoted})`)
|
|
5275
|
+
);
|
|
5276
|
+
}
|
|
5277
|
+
} catch {
|
|
5278
|
+
memSpinner.stop("Memory consolidation skipped");
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
4930
5281
|
const mcpManager = new McpManager();
|
|
4931
5282
|
const mcpSpinner = p2.spinner();
|
|
4932
5283
|
mcpSpinner.start("Connecting to MCP servers");
|
|
@@ -4941,24 +5292,9 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
4941
5292
|
mcpSpinner.stop("MCP connected");
|
|
4942
5293
|
if (mcpTools.length > 0) {
|
|
4943
5294
|
p2.log.success(`${mcpTools.length} MCP tools available`);
|
|
4944
|
-
{
|
|
4945
|
-
const memSpinner = p2.spinner();
|
|
4946
|
-
memSpinner.start("Consolidating memory");
|
|
4947
|
-
try {
|
|
4948
|
-
const report = memoryConsolidate();
|
|
4949
|
-
memSpinner.stop("Memory consolidated");
|
|
4950
|
-
if (report.merged > 0 || report.pruned > 0 || report.promoted > 0) {
|
|
4951
|
-
p2.log.info(
|
|
4952
|
-
`Memory health: ${report.healthScore ?? "?"}% ` + pc7.dim(`(merged ${report.merged}, pruned ${report.pruned}, promoted ${report.promoted})`)
|
|
4953
|
-
);
|
|
4954
|
-
}
|
|
4955
|
-
} catch {
|
|
4956
|
-
memSpinner.stop("Memory consolidation skipped");
|
|
4957
|
-
}
|
|
4958
|
-
}
|
|
4959
5295
|
} else {
|
|
4960
5296
|
p2.log.info(
|
|
4961
|
-
"No MCP tools connected (install aman-mcp
|
|
5297
|
+
"No MCP tools connected (install aman-mcp for tool support)"
|
|
4962
5298
|
);
|
|
4963
5299
|
}
|
|
4964
5300
|
const toolDefs = mcpTools.map((t) => ({
|