@aman_asmuei/aman-agent 0.16.2 → 0.17.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/dist/index.js +347 -311
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -797,18 +797,18 @@ var McpManager = class {
|
|
|
797
797
|
|
|
798
798
|
// src/agent.ts
|
|
799
799
|
import * as readline from "readline";
|
|
800
|
-
import
|
|
801
|
-
import
|
|
802
|
-
import
|
|
800
|
+
import fs13 from "fs";
|
|
801
|
+
import path13 from "path";
|
|
802
|
+
import os12 from "os";
|
|
803
803
|
import pc6 from "picocolors";
|
|
804
804
|
import { marked } from "marked";
|
|
805
805
|
import { markedTerminal } from "marked-terminal";
|
|
806
806
|
import logUpdate from "log-update";
|
|
807
807
|
|
|
808
808
|
// src/commands.ts
|
|
809
|
-
import
|
|
810
|
-
import
|
|
811
|
-
import
|
|
809
|
+
import fs9 from "fs";
|
|
810
|
+
import path9 from "path";
|
|
811
|
+
import os9 from "os";
|
|
812
812
|
import { execFileSync } from "child_process";
|
|
813
813
|
import pc3 from "picocolors";
|
|
814
814
|
|
|
@@ -869,10 +869,85 @@ function getEcosystemStatus(mcpToolCount, amemConnected) {
|
|
|
869
869
|
};
|
|
870
870
|
}
|
|
871
871
|
|
|
872
|
-
// src/
|
|
873
|
-
import
|
|
872
|
+
// src/memory.ts
|
|
873
|
+
import {
|
|
874
|
+
createDatabase,
|
|
875
|
+
recall,
|
|
876
|
+
buildContext,
|
|
877
|
+
storeMemory,
|
|
878
|
+
consolidateMemories,
|
|
879
|
+
cosineSimilarity,
|
|
880
|
+
preloadEmbeddings,
|
|
881
|
+
buildVectorIndex
|
|
882
|
+
} from "@aman_asmuei/amem-core";
|
|
874
883
|
import path5 from "path";
|
|
875
884
|
import os5 from "os";
|
|
885
|
+
import fs5 from "fs";
|
|
886
|
+
var db = null;
|
|
887
|
+
var currentProject = "global";
|
|
888
|
+
async function initMemory(project) {
|
|
889
|
+
if (db) return db;
|
|
890
|
+
const amemDir = process.env.AMEM_DIR ?? path5.join(os5.homedir(), ".amem");
|
|
891
|
+
if (!fs5.existsSync(amemDir)) fs5.mkdirSync(amemDir, { recursive: true });
|
|
892
|
+
const dbPath = process.env.AMEM_DB ?? path5.join(amemDir, "memory.db");
|
|
893
|
+
db = createDatabase(dbPath);
|
|
894
|
+
currentProject = project ?? "global";
|
|
895
|
+
preloadEmbeddings();
|
|
896
|
+
setTimeout(() => {
|
|
897
|
+
try {
|
|
898
|
+
buildVectorIndex(db);
|
|
899
|
+
} catch {
|
|
900
|
+
}
|
|
901
|
+
}, 1e3);
|
|
902
|
+
return db;
|
|
903
|
+
}
|
|
904
|
+
function getDb() {
|
|
905
|
+
if (!db) throw new Error("Memory not initialized \u2014 call initMemory() first");
|
|
906
|
+
return db;
|
|
907
|
+
}
|
|
908
|
+
async function memoryRecall(query, opts) {
|
|
909
|
+
return recall(getDb(), {
|
|
910
|
+
query,
|
|
911
|
+
limit: opts?.limit ?? 10,
|
|
912
|
+
compact: opts?.compact ?? true,
|
|
913
|
+
type: opts?.type,
|
|
914
|
+
tag: opts?.tag,
|
|
915
|
+
minConfidence: opts?.minConfidence,
|
|
916
|
+
explain: opts?.explain,
|
|
917
|
+
scope: currentProject
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
async function memoryContext(topic, maxTokens) {
|
|
921
|
+
return buildContext(getDb(), topic, { maxTokens, scope: currentProject });
|
|
922
|
+
}
|
|
923
|
+
async function memoryStore(opts) {
|
|
924
|
+
return storeMemory(getDb(), opts);
|
|
925
|
+
}
|
|
926
|
+
function memoryLog(sessionId, role, content) {
|
|
927
|
+
return getDb().appendLog({
|
|
928
|
+
sessionId,
|
|
929
|
+
role,
|
|
930
|
+
content,
|
|
931
|
+
project: currentProject,
|
|
932
|
+
metadata: {}
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
function reminderCheck() {
|
|
936
|
+
return getDb().checkReminders();
|
|
937
|
+
}
|
|
938
|
+
function memoryConsolidate(dryRun = false) {
|
|
939
|
+
return consolidateMemories(getDb(), cosineSimilarity, {
|
|
940
|
+
dryRun,
|
|
941
|
+
maxStaleDays: 90,
|
|
942
|
+
minConfidence: 0.3,
|
|
943
|
+
minAccessCount: 0
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// src/profile-templates.ts
|
|
948
|
+
import fs6 from "fs";
|
|
949
|
+
import path6 from "path";
|
|
950
|
+
import os6 from "os";
|
|
876
951
|
var BUILT_IN_PROFILES = [
|
|
877
952
|
{
|
|
878
953
|
name: "coder",
|
|
@@ -965,9 +1040,9 @@ var BUILT_IN_PROFILES = [
|
|
|
965
1040
|
function installProfileTemplate(templateName, userName) {
|
|
966
1041
|
const template = BUILT_IN_PROFILES.find((t) => t.name === templateName);
|
|
967
1042
|
if (!template) return null;
|
|
968
|
-
const profileDir =
|
|
969
|
-
if (
|
|
970
|
-
|
|
1043
|
+
const profileDir = path6.join(os6.homedir(), ".acore", "profiles", template.name);
|
|
1044
|
+
if (fs6.existsSync(profileDir)) return `Profile already exists: ${template.name}`;
|
|
1045
|
+
fs6.mkdirSync(profileDir, { recursive: true });
|
|
971
1046
|
let core = template.core;
|
|
972
1047
|
if (userName) {
|
|
973
1048
|
core += `
|
|
@@ -981,12 +1056,12 @@ function installProfileTemplate(templateName, userName) {
|
|
|
981
1056
|
- Detail level: balanced
|
|
982
1057
|
`;
|
|
983
1058
|
}
|
|
984
|
-
|
|
1059
|
+
fs6.writeFileSync(path6.join(profileDir, "core.md"), core, "utf-8");
|
|
985
1060
|
if (template.rules) {
|
|
986
|
-
|
|
1061
|
+
fs6.writeFileSync(path6.join(profileDir, "rules.md"), template.rules, "utf-8");
|
|
987
1062
|
}
|
|
988
1063
|
if (template.skills) {
|
|
989
|
-
|
|
1064
|
+
fs6.writeFileSync(path6.join(profileDir, "skills.md"), template.skills, "utf-8");
|
|
990
1065
|
}
|
|
991
1066
|
return null;
|
|
992
1067
|
}
|
|
@@ -1113,43 +1188,43 @@ async function delegatePipeline(steps, initialInput, client, mcpManager, options
|
|
|
1113
1188
|
}
|
|
1114
1189
|
|
|
1115
1190
|
// src/teams.ts
|
|
1116
|
-
import
|
|
1117
|
-
import
|
|
1118
|
-
import
|
|
1191
|
+
import fs7 from "fs";
|
|
1192
|
+
import path7 from "path";
|
|
1193
|
+
import os7 from "os";
|
|
1119
1194
|
import pc2 from "picocolors";
|
|
1120
1195
|
function getTeamsDir() {
|
|
1121
|
-
return
|
|
1196
|
+
return path7.join(os7.homedir(), ".acore", "teams");
|
|
1122
1197
|
}
|
|
1123
1198
|
function ensureTeamsDir() {
|
|
1124
1199
|
const dir = getTeamsDir();
|
|
1125
|
-
if (!
|
|
1200
|
+
if (!fs7.existsSync(dir)) fs7.mkdirSync(dir, { recursive: true });
|
|
1126
1201
|
return dir;
|
|
1127
1202
|
}
|
|
1128
1203
|
function teamPath(name) {
|
|
1129
1204
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
1130
|
-
return
|
|
1205
|
+
return path7.join(ensureTeamsDir(), `${slug}.json`);
|
|
1131
1206
|
}
|
|
1132
1207
|
function createTeam(team) {
|
|
1133
1208
|
const fp = teamPath(team.name);
|
|
1134
|
-
|
|
1209
|
+
fs7.writeFileSync(fp, JSON.stringify(team, null, 2), "utf-8");
|
|
1135
1210
|
}
|
|
1136
1211
|
function loadTeam(name) {
|
|
1137
1212
|
const fp = teamPath(name);
|
|
1138
|
-
if (!
|
|
1213
|
+
if (!fs7.existsSync(fp)) return null;
|
|
1139
1214
|
try {
|
|
1140
|
-
return JSON.parse(
|
|
1215
|
+
return JSON.parse(fs7.readFileSync(fp, "utf-8"));
|
|
1141
1216
|
} catch {
|
|
1142
1217
|
return null;
|
|
1143
1218
|
}
|
|
1144
1219
|
}
|
|
1145
1220
|
function listTeams() {
|
|
1146
1221
|
const dir = getTeamsDir();
|
|
1147
|
-
if (!
|
|
1222
|
+
if (!fs7.existsSync(dir)) return [];
|
|
1148
1223
|
const teams = [];
|
|
1149
|
-
for (const file of
|
|
1224
|
+
for (const file of fs7.readdirSync(dir)) {
|
|
1150
1225
|
if (!file.endsWith(".json")) continue;
|
|
1151
1226
|
try {
|
|
1152
|
-
const content =
|
|
1227
|
+
const content = fs7.readFileSync(path7.join(dir, file), "utf-8");
|
|
1153
1228
|
teams.push(JSON.parse(content));
|
|
1154
1229
|
} catch {
|
|
1155
1230
|
}
|
|
@@ -1158,8 +1233,8 @@ function listTeams() {
|
|
|
1158
1233
|
}
|
|
1159
1234
|
function deleteTeam(name) {
|
|
1160
1235
|
const fp = teamPath(name);
|
|
1161
|
-
if (!
|
|
1162
|
-
|
|
1236
|
+
if (!fs7.existsSync(fp)) return false;
|
|
1237
|
+
fs7.unlinkSync(fp);
|
|
1163
1238
|
return true;
|
|
1164
1239
|
}
|
|
1165
1240
|
async function runTeam(team, task, client, mcpManager, tools) {
|
|
@@ -1385,23 +1460,23 @@ var BUILT_IN_TEAMS = [
|
|
|
1385
1460
|
];
|
|
1386
1461
|
|
|
1387
1462
|
// src/plans.ts
|
|
1388
|
-
import
|
|
1389
|
-
import
|
|
1390
|
-
import
|
|
1463
|
+
import fs8 from "fs";
|
|
1464
|
+
import path8 from "path";
|
|
1465
|
+
import os8 from "os";
|
|
1391
1466
|
function getPlansDir() {
|
|
1392
|
-
const localDir =
|
|
1393
|
-
const localAcore =
|
|
1394
|
-
if (
|
|
1395
|
-
return
|
|
1467
|
+
const localDir = path8.join(process.cwd(), ".acore", "plans");
|
|
1468
|
+
const localAcore = path8.join(process.cwd(), ".acore");
|
|
1469
|
+
if (fs8.existsSync(localAcore)) return localDir;
|
|
1470
|
+
return path8.join(os8.homedir(), ".acore", "plans");
|
|
1396
1471
|
}
|
|
1397
1472
|
function ensurePlansDir() {
|
|
1398
1473
|
const dir = getPlansDir();
|
|
1399
|
-
if (!
|
|
1474
|
+
if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
|
|
1400
1475
|
return dir;
|
|
1401
1476
|
}
|
|
1402
1477
|
function planPath(name) {
|
|
1403
1478
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
1404
|
-
return
|
|
1479
|
+
return path8.join(ensurePlansDir(), `${slug}.md`);
|
|
1405
1480
|
}
|
|
1406
1481
|
function serializePlan(plan) {
|
|
1407
1482
|
const lines = [];
|
|
@@ -1427,7 +1502,7 @@ function parsePlan(content, filePath) {
|
|
|
1427
1502
|
const createdMatch = content.match(/\*\*Created:\*\*\s*(.+)/);
|
|
1428
1503
|
const updatedMatch = content.match(/\*\*Updated:\*\*\s*(.+)/);
|
|
1429
1504
|
const activeMatch = content.match(/\*\*Active:\*\*\s*(.+)/);
|
|
1430
|
-
const name = nameMatch?.[1]?.trim() ||
|
|
1505
|
+
const name = nameMatch?.[1]?.trim() || path8.basename(filePath, ".md");
|
|
1431
1506
|
const goal = goalMatch?.[1]?.trim() || "";
|
|
1432
1507
|
const createdAt = createdMatch?.[1]?.trim() || "";
|
|
1433
1508
|
const updatedAt = updatedMatch?.[1]?.trim() || "";
|
|
@@ -1469,22 +1544,22 @@ function createPlan(name, goal, steps) {
|
|
|
1469
1544
|
}
|
|
1470
1545
|
function savePlan(plan) {
|
|
1471
1546
|
const fp = planPath(plan.name);
|
|
1472
|
-
|
|
1547
|
+
fs8.writeFileSync(fp, serializePlan(plan), "utf-8");
|
|
1473
1548
|
}
|
|
1474
1549
|
function loadPlan(name) {
|
|
1475
1550
|
const fp = planPath(name);
|
|
1476
|
-
if (!
|
|
1477
|
-
const content =
|
|
1551
|
+
if (!fs8.existsSync(fp)) return null;
|
|
1552
|
+
const content = fs8.readFileSync(fp, "utf-8");
|
|
1478
1553
|
return parsePlan(content, fp);
|
|
1479
1554
|
}
|
|
1480
1555
|
function listPlans() {
|
|
1481
1556
|
const dir = getPlansDir();
|
|
1482
|
-
if (!
|
|
1557
|
+
if (!fs8.existsSync(dir)) return [];
|
|
1483
1558
|
const plans = [];
|
|
1484
|
-
for (const file of
|
|
1559
|
+
for (const file of fs8.readdirSync(dir)) {
|
|
1485
1560
|
if (!file.endsWith(".md")) continue;
|
|
1486
|
-
const fp =
|
|
1487
|
-
const content =
|
|
1561
|
+
const fp = path8.join(dir, file);
|
|
1562
|
+
const content = fs8.readFileSync(fp, "utf-8");
|
|
1488
1563
|
const plan = parsePlan(content, fp);
|
|
1489
1564
|
if (plan) plans.push(plan);
|
|
1490
1565
|
}
|
|
@@ -1580,10 +1655,10 @@ function progressBar(pct) {
|
|
|
1580
1655
|
|
|
1581
1656
|
// src/commands.ts
|
|
1582
1657
|
function readEcosystemFile(filePath, label) {
|
|
1583
|
-
if (!
|
|
1658
|
+
if (!fs9.existsSync(filePath)) {
|
|
1584
1659
|
return pc3.dim(`No ${label} file found at ${filePath}`);
|
|
1585
1660
|
}
|
|
1586
|
-
return
|
|
1661
|
+
return fs9.readFileSync(filePath, "utf-8").trim();
|
|
1587
1662
|
}
|
|
1588
1663
|
function parseCommand(input) {
|
|
1589
1664
|
const trimmed = input.trim();
|
|
@@ -1604,9 +1679,9 @@ async function mcpWrite(ctx, layer, tool, args) {
|
|
|
1604
1679
|
return pc3.green(result);
|
|
1605
1680
|
}
|
|
1606
1681
|
async function handleIdentityCommand(action, args, ctx) {
|
|
1607
|
-
const home2 =
|
|
1682
|
+
const home2 = os9.homedir();
|
|
1608
1683
|
if (!action) {
|
|
1609
|
-
const content = readEcosystemFile(
|
|
1684
|
+
const content = readEcosystemFile(path9.join(home2, ".acore", "core.md"), "identity (acore)");
|
|
1610
1685
|
return { handled: true, output: content };
|
|
1611
1686
|
}
|
|
1612
1687
|
if (action === "update") {
|
|
@@ -1630,9 +1705,9 @@ async function handleIdentityCommand(action, args, ctx) {
|
|
|
1630
1705
|
return { handled: true, output: pc3.yellow(`Unknown action: /identity ${action}. Use /identity or /identity update <section>.`) };
|
|
1631
1706
|
}
|
|
1632
1707
|
async function handleRulesCommand(action, args, ctx) {
|
|
1633
|
-
const home2 =
|
|
1708
|
+
const home2 = os9.homedir();
|
|
1634
1709
|
if (!action) {
|
|
1635
|
-
const content = readEcosystemFile(
|
|
1710
|
+
const content = readEcosystemFile(path9.join(home2, ".arules", "rules.md"), "guardrails (arules)");
|
|
1636
1711
|
return { handled: true, output: content };
|
|
1637
1712
|
}
|
|
1638
1713
|
if (action === "add") {
|
|
@@ -1661,9 +1736,9 @@ async function handleRulesCommand(action, args, ctx) {
|
|
|
1661
1736
|
return { handled: true, output: pc3.yellow(`Unknown action: /rules ${action}. Use /rules [add|remove|toggle].`) };
|
|
1662
1737
|
}
|
|
1663
1738
|
async function handleWorkflowsCommand(action, args, ctx) {
|
|
1664
|
-
const home2 =
|
|
1739
|
+
const home2 = os9.homedir();
|
|
1665
1740
|
if (!action) {
|
|
1666
|
-
const content = readEcosystemFile(
|
|
1741
|
+
const content = readEcosystemFile(path9.join(home2, ".aflow", "flow.md"), "workflows (aflow)");
|
|
1667
1742
|
return { handled: true, output: content };
|
|
1668
1743
|
}
|
|
1669
1744
|
if (action === "add") {
|
|
@@ -1702,38 +1777,38 @@ var AKIT_REGISTRY = [
|
|
|
1702
1777
|
{ name: "docling", description: "Convert PDF, DOCX, PPTX, XLSX to markdown", category: "documents", mcp: { package: "docling-mcp", command: "uvx", args: ["docling-mcp"] }, envHint: "Requires Python 3.10+. Install: pip install docling" }
|
|
1703
1778
|
];
|
|
1704
1779
|
function loadAkitInstalled() {
|
|
1705
|
-
const filePath =
|
|
1706
|
-
if (!
|
|
1780
|
+
const filePath = path9.join(os9.homedir(), ".akit", "installed.json");
|
|
1781
|
+
if (!fs9.existsSync(filePath)) return [];
|
|
1707
1782
|
try {
|
|
1708
|
-
return JSON.parse(
|
|
1783
|
+
return JSON.parse(fs9.readFileSync(filePath, "utf-8"));
|
|
1709
1784
|
} catch {
|
|
1710
1785
|
return [];
|
|
1711
1786
|
}
|
|
1712
1787
|
}
|
|
1713
1788
|
function saveAkitInstalled(tools) {
|
|
1714
|
-
const dir =
|
|
1715
|
-
|
|
1716
|
-
|
|
1789
|
+
const dir = path9.join(os9.homedir(), ".akit");
|
|
1790
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
1791
|
+
fs9.writeFileSync(path9.join(dir, "installed.json"), JSON.stringify(tools, null, 2) + "\n", "utf-8");
|
|
1717
1792
|
}
|
|
1718
1793
|
function addToAmanAgentConfig(name, mcpConfig) {
|
|
1719
|
-
const configPath =
|
|
1720
|
-
if (!
|
|
1794
|
+
const configPath = path9.join(os9.homedir(), ".aman-agent", "config.json");
|
|
1795
|
+
if (!fs9.existsSync(configPath)) return;
|
|
1721
1796
|
try {
|
|
1722
|
-
const config = JSON.parse(
|
|
1797
|
+
const config = JSON.parse(fs9.readFileSync(configPath, "utf-8"));
|
|
1723
1798
|
if (!config.mcpServers) config.mcpServers = {};
|
|
1724
1799
|
config.mcpServers[name] = mcpConfig;
|
|
1725
|
-
|
|
1800
|
+
fs9.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1726
1801
|
} catch {
|
|
1727
1802
|
}
|
|
1728
1803
|
}
|
|
1729
1804
|
function removeFromAmanAgentConfig(name) {
|
|
1730
|
-
const configPath =
|
|
1731
|
-
if (!
|
|
1805
|
+
const configPath = path9.join(os9.homedir(), ".aman-agent", "config.json");
|
|
1806
|
+
if (!fs9.existsSync(configPath)) return;
|
|
1732
1807
|
try {
|
|
1733
|
-
const config = JSON.parse(
|
|
1808
|
+
const config = JSON.parse(fs9.readFileSync(configPath, "utf-8"));
|
|
1734
1809
|
if (config.mcpServers) {
|
|
1735
1810
|
delete config.mcpServers[name];
|
|
1736
|
-
|
|
1811
|
+
fs9.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1737
1812
|
}
|
|
1738
1813
|
} catch {
|
|
1739
1814
|
}
|
|
@@ -1883,9 +1958,9 @@ function handleAkitCommand(action, args) {
|
|
|
1883
1958
|
return { handled: true, output: lines.join("\n") };
|
|
1884
1959
|
}
|
|
1885
1960
|
async function handleSkillsCommand(action, args, ctx) {
|
|
1886
|
-
const home2 =
|
|
1961
|
+
const home2 = os9.homedir();
|
|
1887
1962
|
if (!action) {
|
|
1888
|
-
const content = readEcosystemFile(
|
|
1963
|
+
const content = readEcosystemFile(path9.join(home2, ".askill", "skills.md"), "skills (askill)");
|
|
1889
1964
|
return { handled: true, output: content };
|
|
1890
1965
|
}
|
|
1891
1966
|
if (action === "install") {
|
|
@@ -1905,9 +1980,9 @@ async function handleSkillsCommand(action, args, ctx) {
|
|
|
1905
1980
|
return { handled: true, output: pc3.yellow(`Unknown action: /skills ${action}. Use /skills [install|uninstall].`) };
|
|
1906
1981
|
}
|
|
1907
1982
|
async function handleEvalCommand(action, args, ctx) {
|
|
1908
|
-
const home2 =
|
|
1983
|
+
const home2 = os9.homedir();
|
|
1909
1984
|
if (!action) {
|
|
1910
|
-
const content = readEcosystemFile(
|
|
1985
|
+
const content = readEcosystemFile(path9.join(home2, ".aeval", "eval.md"), "evaluation (aeval)");
|
|
1911
1986
|
return { handled: true, output: content };
|
|
1912
1987
|
}
|
|
1913
1988
|
if (action === "milestone") {
|
|
@@ -1922,36 +1997,39 @@ async function handleEvalCommand(action, args, ctx) {
|
|
|
1922
1997
|
}
|
|
1923
1998
|
async function handleMemoryCommand(action, args, ctx) {
|
|
1924
1999
|
if (!action) {
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
output: pc3.
|
|
1929
|
-
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
return { handled: true, output: pc3.red(result) };
|
|
2000
|
+
try {
|
|
2001
|
+
const result = await memoryContext("recent context");
|
|
2002
|
+
if (result.memoriesUsed === 0) {
|
|
2003
|
+
return { handled: true, output: pc3.dim("No memories yet. Start chatting and I'll remember what matters.") };
|
|
2004
|
+
}
|
|
2005
|
+
return { handled: true, output: result.text };
|
|
2006
|
+
} catch (err) {
|
|
2007
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
1934
2008
|
}
|
|
1935
|
-
return { handled: true, output: result };
|
|
1936
2009
|
}
|
|
1937
2010
|
if (action && !["search", "clear", "timeline"].includes(action)) {
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
return { handled: true, output:
|
|
2011
|
+
try {
|
|
2012
|
+
const topic = [action, ...args].join(" ");
|
|
2013
|
+
const result = await memoryContext(topic);
|
|
2014
|
+
if (result.memoriesUsed === 0) {
|
|
2015
|
+
return { handled: true, output: pc3.dim(`No memories found for: "${topic}".`) };
|
|
2016
|
+
}
|
|
2017
|
+
return { handled: true, output: result.text };
|
|
2018
|
+
} catch (err) {
|
|
2019
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
1945
2020
|
}
|
|
1946
|
-
return { handled: true, output: result };
|
|
1947
2021
|
}
|
|
1948
2022
|
if (action === "search") {
|
|
1949
2023
|
if (args.length < 1) {
|
|
1950
2024
|
return { handled: true, output: pc3.yellow("Usage: /memory search <query...>") };
|
|
1951
2025
|
}
|
|
1952
2026
|
const query = args.join(" ");
|
|
1953
|
-
|
|
1954
|
-
|
|
2027
|
+
try {
|
|
2028
|
+
const result = await memoryRecall(query);
|
|
2029
|
+
return { handled: true, output: result.total === 0 ? pc3.dim("No memories found.") : result.text };
|
|
2030
|
+
} catch (err) {
|
|
2031
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2032
|
+
}
|
|
1955
2033
|
}
|
|
1956
2034
|
if (action === "clear") {
|
|
1957
2035
|
if (args.length < 1) {
|
|
@@ -1961,50 +2039,45 @@ async function handleMemoryCommand(action, args, ctx) {
|
|
|
1961
2039
|
return { handled: true, output };
|
|
1962
2040
|
}
|
|
1963
2041
|
if (action === "timeline") {
|
|
1964
|
-
if (!ctx.mcpManager) {
|
|
1965
|
-
return { handled: true, output: pc3.red("Memory not available: MCP not connected.") };
|
|
1966
|
-
}
|
|
1967
2042
|
try {
|
|
1968
|
-
const result = await
|
|
1969
|
-
if (result.
|
|
2043
|
+
const result = await memoryRecall("*", { limit: 500, compact: false });
|
|
2044
|
+
if (result.total === 0) {
|
|
1970
2045
|
return { handled: true, output: pc3.dim("No memories yet. Start chatting and I'll remember what matters.") };
|
|
1971
2046
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
2047
|
+
const memories = result.memories;
|
|
2048
|
+
if (memories.length > 0) {
|
|
2049
|
+
const byDate = /* @__PURE__ */ new Map();
|
|
2050
|
+
for (const mem of memories) {
|
|
2051
|
+
const createdAt = mem.created_at;
|
|
2052
|
+
const date = createdAt ? new Date(createdAt).toLocaleDateString("en-US", { month: "short", day: "numeric" }) : "Unknown";
|
|
2053
|
+
byDate.set(date, (byDate.get(date) || 0) + 1);
|
|
2054
|
+
}
|
|
2055
|
+
const maxCount = Math.max(...byDate.values());
|
|
2056
|
+
const barWidth = 10;
|
|
2057
|
+
const lines = [pc3.bold("Memory Timeline:"), ""];
|
|
2058
|
+
for (const [date, count] of byDate) {
|
|
2059
|
+
const filled = Math.round(count / maxCount * barWidth);
|
|
2060
|
+
const bar = "\u2588".repeat(filled) + "\u2591".repeat(barWidth - filled);
|
|
2061
|
+
lines.push(` ${date.padEnd(8)} ${bar} ${count} memories`);
|
|
2062
|
+
}
|
|
2063
|
+
const tags = /* @__PURE__ */ new Map();
|
|
2064
|
+
for (const mem of memories) {
|
|
2065
|
+
const memTags = mem.tags;
|
|
2066
|
+
if (Array.isArray(memTags)) {
|
|
2067
|
+
for (const tag of memTags) {
|
|
2068
|
+
tags.set(tag, (tags.get(tag) || 0) + 1);
|
|
1994
2069
|
}
|
|
1995
2070
|
}
|
|
1996
|
-
lines.push("");
|
|
1997
|
-
lines.push(` Total: ${memories.length} memories`);
|
|
1998
|
-
if (tags.size > 0) {
|
|
1999
|
-
const topTags = [...tags.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([tag, count]) => `#${tag} (${count})`).join(", ");
|
|
2000
|
-
lines.push(` Top tags: ${topTags}`);
|
|
2001
|
-
}
|
|
2002
|
-
return { handled: true, output: lines.join("\n") };
|
|
2003
2071
|
}
|
|
2004
|
-
|
|
2072
|
+
lines.push("");
|
|
2073
|
+
lines.push(` Total: ${result.total} memories`);
|
|
2074
|
+
if (tags.size > 0) {
|
|
2075
|
+
const topTags = [...tags.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([tag, count]) => `#${tag} (${count})`).join(", ");
|
|
2076
|
+
lines.push(` Top tags: ${topTags}`);
|
|
2077
|
+
}
|
|
2078
|
+
return { handled: true, output: lines.join("\n") };
|
|
2005
2079
|
}
|
|
2006
|
-
|
|
2007
|
-
return { handled: true, output: `Total memories: ~${lineCount} entries.` };
|
|
2080
|
+
return { handled: true, output: `Total memories: ${result.total} entries.` };
|
|
2008
2081
|
} catch {
|
|
2009
2082
|
return { handled: true, output: pc3.red("Failed to retrieve memory timeline.") };
|
|
2010
2083
|
}
|
|
@@ -2104,13 +2177,13 @@ function handleSave() {
|
|
|
2104
2177
|
return { handled: true, saveConversation: true };
|
|
2105
2178
|
}
|
|
2106
2179
|
function handleReconfig() {
|
|
2107
|
-
const configDir =
|
|
2108
|
-
const configPath =
|
|
2109
|
-
if (
|
|
2110
|
-
|
|
2180
|
+
const configDir = path9.join(os9.homedir(), ".aman-agent");
|
|
2181
|
+
const configPath = path9.join(configDir, "config.json");
|
|
2182
|
+
if (fs9.existsSync(configPath)) {
|
|
2183
|
+
fs9.unlinkSync(configPath);
|
|
2111
2184
|
}
|
|
2112
|
-
|
|
2113
|
-
|
|
2185
|
+
fs9.mkdirSync(configDir, { recursive: true });
|
|
2186
|
+
fs9.writeFileSync(path9.join(configDir, ".reconfig"), "", "utf-8");
|
|
2114
2187
|
return {
|
|
2115
2188
|
handled: true,
|
|
2116
2189
|
quit: true,
|
|
@@ -2123,7 +2196,7 @@ function handleReconfig() {
|
|
|
2123
2196
|
function handleUpdate() {
|
|
2124
2197
|
try {
|
|
2125
2198
|
const current = execFileSync("npm", ["view", "@aman_asmuei/aman-agent", "version"], { encoding: "utf-8" }).trim();
|
|
2126
|
-
const local = JSON.parse(
|
|
2199
|
+
const local = JSON.parse(fs9.readFileSync(path9.join(__dirname, "..", "package.json"), "utf-8")).version;
|
|
2127
2200
|
if (current === local) {
|
|
2128
2201
|
return { handled: true, output: `${pc3.green("Up to date")} \u2014 v${local}` };
|
|
2129
2202
|
}
|
|
@@ -2152,31 +2225,26 @@ function handleUpdate() {
|
|
|
2152
2225
|
};
|
|
2153
2226
|
}
|
|
2154
2227
|
}
|
|
2155
|
-
async function handleDecisionsCommand(action, _args,
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
...scope ? { scope } : {}
|
|
2165
|
-
});
|
|
2166
|
-
if (result.startsWith("Error")) {
|
|
2167
|
-
return { handled: true, output: pc3.red(result) };
|
|
2228
|
+
async function handleDecisionsCommand(action, _args, _ctx) {
|
|
2229
|
+
try {
|
|
2230
|
+
const result = await memoryRecall("decision", { type: "decision", limit: 20 });
|
|
2231
|
+
if (result.total === 0) {
|
|
2232
|
+
return { handled: true, output: pc3.dim("No decisions recorded yet.") };
|
|
2233
|
+
}
|
|
2234
|
+
return { handled: true, output: pc3.bold("Decision Log:\n") + result.text };
|
|
2235
|
+
} catch (err) {
|
|
2236
|
+
return { handled: true, output: pc3.red(`Memory error: ${err instanceof Error ? err.message : String(err)}`) };
|
|
2168
2237
|
}
|
|
2169
|
-
return { handled: true, output: pc3.bold("Decision Log:\n") + result };
|
|
2170
2238
|
}
|
|
2171
2239
|
function handleExportCommand() {
|
|
2172
2240
|
return { handled: true, exportConversation: true };
|
|
2173
2241
|
}
|
|
2174
2242
|
function handleDebugCommand() {
|
|
2175
|
-
const logPath =
|
|
2176
|
-
if (!
|
|
2243
|
+
const logPath = path9.join(os9.homedir(), ".aman-agent", "debug.log");
|
|
2244
|
+
if (!fs9.existsSync(logPath)) {
|
|
2177
2245
|
return { handled: true, output: pc3.dim("No debug log found.") };
|
|
2178
2246
|
}
|
|
2179
|
-
const content =
|
|
2247
|
+
const content = fs9.readFileSync(logPath, "utf-8");
|
|
2180
2248
|
const lines = content.trim().split("\n");
|
|
2181
2249
|
const last20 = lines.slice(-20).join("\n");
|
|
2182
2250
|
return { handled: true, output: pc3.bold("Debug Log (last 20 entries):\n") + pc3.dim(last20) };
|
|
@@ -2374,7 +2442,7 @@ ${result.response}`
|
|
|
2374
2442
|
};
|
|
2375
2443
|
}
|
|
2376
2444
|
function handleProfileCommand(action, args) {
|
|
2377
|
-
const profilesDir =
|
|
2445
|
+
const profilesDir = path9.join(os9.homedir(), ".acore", "profiles");
|
|
2378
2446
|
if (!action || action === "list") {
|
|
2379
2447
|
const profiles = listProfiles();
|
|
2380
2448
|
if (profiles.length === 0) {
|
|
@@ -2398,8 +2466,8 @@ function handleProfileCommand(action, args) {
|
|
|
2398
2466
|
};
|
|
2399
2467
|
}
|
|
2400
2468
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
2401
|
-
const profileDir =
|
|
2402
|
-
if (
|
|
2469
|
+
const profileDir = path9.join(profilesDir, slug);
|
|
2470
|
+
if (fs9.existsSync(profileDir)) {
|
|
2403
2471
|
return { handled: true, output: pc3.yellow(`Profile already exists: ${slug}`) };
|
|
2404
2472
|
}
|
|
2405
2473
|
const builtIn = BUILT_IN_PROFILES.find((t) => t.name === slug);
|
|
@@ -2415,16 +2483,16 @@ function handleProfileCommand(action, args) {
|
|
|
2415
2483
|
Use: aman-agent --profile ${slug}`
|
|
2416
2484
|
};
|
|
2417
2485
|
}
|
|
2418
|
-
|
|
2419
|
-
const globalCore =
|
|
2420
|
-
if (
|
|
2421
|
-
let content =
|
|
2486
|
+
fs9.mkdirSync(profileDir, { recursive: true });
|
|
2487
|
+
const globalCore = path9.join(os9.homedir(), ".acore", "core.md");
|
|
2488
|
+
if (fs9.existsSync(globalCore)) {
|
|
2489
|
+
let content = fs9.readFileSync(globalCore, "utf-8");
|
|
2422
2490
|
const aiName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
2423
2491
|
content = content.replace(/^# .+$/m, `# ${aiName}`);
|
|
2424
|
-
|
|
2492
|
+
fs9.writeFileSync(path9.join(profileDir, "core.md"), content, "utf-8");
|
|
2425
2493
|
} else {
|
|
2426
2494
|
const aiName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
2427
|
-
|
|
2495
|
+
fs9.writeFileSync(path9.join(profileDir, "core.md"), `# ${aiName}
|
|
2428
2496
|
|
|
2429
2497
|
## Identity
|
|
2430
2498
|
- Role: ${aiName} is your AI companion
|
|
@@ -2437,7 +2505,7 @@ function handleProfileCommand(action, args) {
|
|
|
2437
2505
|
return {
|
|
2438
2506
|
handled: true,
|
|
2439
2507
|
output: pc3.green(`Profile created: ${slug}`) + `
|
|
2440
|
-
Edit: ${
|
|
2508
|
+
Edit: ${path9.join(profileDir, "core.md")}
|
|
2441
2509
|
Use: aman-agent --profile ${slug}
|
|
2442
2510
|
|
|
2443
2511
|
${pc3.dim("Add rules.md or skills.md for profile-specific overrides.")}`
|
|
@@ -2446,9 +2514,9 @@ function handleProfileCommand(action, args) {
|
|
|
2446
2514
|
case "show": {
|
|
2447
2515
|
const name = args[0];
|
|
2448
2516
|
if (!name) return { handled: true, output: pc3.yellow("Usage: /profile show <name>") };
|
|
2449
|
-
const profileDir =
|
|
2450
|
-
if (!
|
|
2451
|
-
const files =
|
|
2517
|
+
const profileDir = path9.join(profilesDir, name);
|
|
2518
|
+
if (!fs9.existsSync(profileDir)) return { handled: true, output: pc3.red(`Profile not found: ${name}`) };
|
|
2519
|
+
const files = fs9.readdirSync(profileDir).filter((f) => f.endsWith(".md"));
|
|
2452
2520
|
const lines = files.map((f) => ` ${f}`);
|
|
2453
2521
|
return { handled: true, output: `Profile: ${pc3.bold(name)}
|
|
2454
2522
|
Files:
|
|
@@ -2457,9 +2525,9 @@ ${lines.join("\n")}` };
|
|
|
2457
2525
|
case "delete": {
|
|
2458
2526
|
const name = args[0];
|
|
2459
2527
|
if (!name) return { handled: true, output: pc3.yellow("Usage: /profile delete <name>") };
|
|
2460
|
-
const profileDir =
|
|
2461
|
-
if (!
|
|
2462
|
-
|
|
2528
|
+
const profileDir = path9.join(profilesDir, name);
|
|
2529
|
+
if (!fs9.existsSync(profileDir)) return { handled: true, output: pc3.red(`Profile not found: ${name}`) };
|
|
2530
|
+
fs9.rmSync(profileDir, { recursive: true });
|
|
2463
2531
|
return { handled: true, output: pc3.dim(`Profile deleted: ${name}`) };
|
|
2464
2532
|
}
|
|
2465
2533
|
case "help":
|
|
@@ -2661,8 +2729,8 @@ async function handleCommand(input, ctx) {
|
|
|
2661
2729
|
// src/hooks.ts
|
|
2662
2730
|
import pc4 from "picocolors";
|
|
2663
2731
|
import * as p from "@clack/prompts";
|
|
2664
|
-
import
|
|
2665
|
-
import
|
|
2732
|
+
import fs10 from "fs";
|
|
2733
|
+
import path10 from "path";
|
|
2666
2734
|
|
|
2667
2735
|
// src/personality.ts
|
|
2668
2736
|
var FRUSTRATION_SIGNALS = [
|
|
@@ -2867,10 +2935,8 @@ async function onSessionStart(ctx) {
|
|
|
2867
2935
|
const visibleReminders = [];
|
|
2868
2936
|
try {
|
|
2869
2937
|
isHookCall = true;
|
|
2870
|
-
const recallResult = await
|
|
2871
|
-
|
|
2872
|
-
firstRun = true;
|
|
2873
|
-
}
|
|
2938
|
+
const recallResult = await memoryRecall("*", { limit: 1 });
|
|
2939
|
+
firstRun = recallResult.total === 0;
|
|
2874
2940
|
} catch {
|
|
2875
2941
|
firstRun = true;
|
|
2876
2942
|
} finally {
|
|
@@ -2900,9 +2966,9 @@ ${contextInjection}`;
|
|
|
2900
2966
|
if (ctx.config.memoryRecall) {
|
|
2901
2967
|
try {
|
|
2902
2968
|
isHookCall = true;
|
|
2903
|
-
const
|
|
2904
|
-
if (
|
|
2905
|
-
greeting +=
|
|
2969
|
+
const contextResult = await memoryContext("session context");
|
|
2970
|
+
if (contextResult.memoriesUsed > 0) {
|
|
2971
|
+
greeting += contextResult.text;
|
|
2906
2972
|
}
|
|
2907
2973
|
} catch (err) {
|
|
2908
2974
|
log.warn("hooks", "memory_context recall failed", err);
|
|
@@ -2933,12 +2999,12 @@ ${contextInjection}`;
|
|
|
2933
2999
|
else greeting = timeContext;
|
|
2934
3000
|
try {
|
|
2935
3001
|
isHookCall = true;
|
|
2936
|
-
const
|
|
2937
|
-
if (
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
for (const
|
|
2941
|
-
visibleReminders.push(
|
|
3002
|
+
const reminders = reminderCheck();
|
|
3003
|
+
if (reminders.length > 0) {
|
|
3004
|
+
const reminderText = reminders.map((r) => r.content).join("\n");
|
|
3005
|
+
greeting += "\n\n<pending-reminders>\n" + reminderText + "\n</pending-reminders>";
|
|
3006
|
+
for (const r of reminders) {
|
|
3007
|
+
visibleReminders.push(r.content);
|
|
2942
3008
|
}
|
|
2943
3009
|
}
|
|
2944
3010
|
} catch (err) {
|
|
@@ -3053,11 +3119,7 @@ async function onSessionEnd(ctx, messages, sessionId) {
|
|
|
3053
3119
|
for (const msg of textMessages) {
|
|
3054
3120
|
try {
|
|
3055
3121
|
isHookCall = true;
|
|
3056
|
-
|
|
3057
|
-
session_id: sessionId,
|
|
3058
|
-
role: msg.role,
|
|
3059
|
-
content: msg.content.slice(0, 5e3)
|
|
3060
|
-
});
|
|
3122
|
+
memoryLog(sessionId, msg.role, msg.content.slice(0, 5e3));
|
|
3061
3123
|
} catch (err) {
|
|
3062
3124
|
log.debug("hooks", "memory_log write failed for " + sessionId, err);
|
|
3063
3125
|
} finally {
|
|
@@ -3085,10 +3147,10 @@ async function onSessionEnd(ctx, messages, sessionId) {
|
|
|
3085
3147
|
}
|
|
3086
3148
|
console.log(pc4.dim(` Saved ${textMessages.length} messages (session: ${sessionId})`));
|
|
3087
3149
|
}
|
|
3088
|
-
const projectContextPath =
|
|
3089
|
-
if (
|
|
3150
|
+
const projectContextPath = path10.join(process.cwd(), ".acore", "context.md");
|
|
3151
|
+
if (fs10.existsSync(projectContextPath) && messages.length > 2) {
|
|
3090
3152
|
try {
|
|
3091
|
-
let contextContent =
|
|
3153
|
+
let contextContent = fs10.readFileSync(projectContextPath, "utf-8");
|
|
3092
3154
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
3093
3155
|
let lastUserMsg = "";
|
|
3094
3156
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -3106,7 +3168,7 @@ async function onSessionEnd(ctx, messages, sessionId) {
|
|
|
3106
3168
|
- Recent decisions: [see memory]
|
|
3107
3169
|
- Temp notes: [cleared]`;
|
|
3108
3170
|
contextContent = contextContent.replace(sessionPattern, newSession);
|
|
3109
|
-
|
|
3171
|
+
fs10.writeFileSync(projectContextPath, contextContent, "utf-8");
|
|
3110
3172
|
log.debug("hooks", `Updated project context: ${projectContextPath}`);
|
|
3111
3173
|
}
|
|
3112
3174
|
} catch (err) {
|
|
@@ -3236,9 +3298,9 @@ ${summaryParts.slice(0, 20).join("\n")}
|
|
|
3236
3298
|
}
|
|
3237
3299
|
|
|
3238
3300
|
// src/skill-engine.ts
|
|
3239
|
-
import
|
|
3240
|
-
import
|
|
3241
|
-
import
|
|
3301
|
+
import fs11 from "fs";
|
|
3302
|
+
import path11 from "path";
|
|
3303
|
+
import os10 from "os";
|
|
3242
3304
|
var SKILL_TRIGGERS = {
|
|
3243
3305
|
testing: ["test", "spec", "coverage", "tdd", "jest", "vitest", "mocha", "assert", "mock", "stub", "fixture", "e2e", "integration test", "unit test"],
|
|
3244
3306
|
"api-design": ["api", "endpoint", "rest", "graphql", "route", "controller", "middleware", "http", "request", "response", "status code", "pagination"],
|
|
@@ -3253,20 +3315,20 @@ var SKILL_TRIGGERS = {
|
|
|
3253
3315
|
typescript: ["typescript", "type", "interface", "generic", "infer", "utility type", "zod", "discriminated union", "type guard", "as const"],
|
|
3254
3316
|
accessibility: ["accessibility", "a11y", "aria", "screen reader", "wcag", "semantic html", "tab order", "focus", "contrast"]
|
|
3255
3317
|
};
|
|
3256
|
-
var LEVEL_FILE =
|
|
3318
|
+
var LEVEL_FILE = path11.join(os10.homedir(), ".aman-agent", "skill-levels.json");
|
|
3257
3319
|
function loadSkillLevels() {
|
|
3258
3320
|
try {
|
|
3259
|
-
if (
|
|
3260
|
-
return JSON.parse(
|
|
3321
|
+
if (fs11.existsSync(LEVEL_FILE)) {
|
|
3322
|
+
return JSON.parse(fs11.readFileSync(LEVEL_FILE, "utf-8"));
|
|
3261
3323
|
}
|
|
3262
3324
|
} catch {
|
|
3263
3325
|
}
|
|
3264
3326
|
return {};
|
|
3265
3327
|
}
|
|
3266
3328
|
function saveSkillLevels(levels) {
|
|
3267
|
-
const dir =
|
|
3268
|
-
if (!
|
|
3269
|
-
|
|
3329
|
+
const dir = path11.dirname(LEVEL_FILE);
|
|
3330
|
+
if (!fs11.existsSync(dir)) fs11.mkdirSync(dir, { recursive: true });
|
|
3331
|
+
fs11.writeFileSync(LEVEL_FILE, JSON.stringify(levels, null, 2), "utf-8");
|
|
3270
3332
|
}
|
|
3271
3333
|
function computeLevel(activations) {
|
|
3272
3334
|
if (activations >= 50) return { level: 5, label: "Expert" };
|
|
@@ -3644,7 +3706,7 @@ function parseExtractionResult(raw) {
|
|
|
3644
3706
|
return [];
|
|
3645
3707
|
}
|
|
3646
3708
|
}
|
|
3647
|
-
async function extractMemories(userMessage, assistantResponse, client,
|
|
3709
|
+
async function extractMemories(userMessage, assistantResponse, client, state) {
|
|
3648
3710
|
if (!shouldExtract(assistantResponse, state.turnsSinceLastExtraction, state.lastExtractionCount)) {
|
|
3649
3711
|
state.turnsSinceLastExtraction++;
|
|
3650
3712
|
return 0;
|
|
@@ -3668,24 +3730,18 @@ Assistant: ${assistantResponse.slice(0, 2e3)}`;
|
|
|
3668
3730
|
let stored = 0;
|
|
3669
3731
|
for (const candidate of candidates) {
|
|
3670
3732
|
try {
|
|
3671
|
-
const existing = await
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
const parsed = JSON.parse(existing);
|
|
3678
|
-
if (Array.isArray(parsed) && parsed.length > 0 && parsed[0].score > 0.85) {
|
|
3679
|
-
log.debug("extractor", "Skipping duplicate: " + candidate.content);
|
|
3680
|
-
continue;
|
|
3681
|
-
}
|
|
3682
|
-
} catch {
|
|
3733
|
+
const existing = await memoryRecall(candidate.content, { limit: 1 });
|
|
3734
|
+
if (existing.total > 0 && existing.memories.length > 0) {
|
|
3735
|
+
const topScore = existing.memories[0]?.score;
|
|
3736
|
+
if (topScore && topScore > 0.85) {
|
|
3737
|
+
log.debug("extractor", "Skipping duplicate: " + candidate.content);
|
|
3738
|
+
continue;
|
|
3683
3739
|
}
|
|
3684
3740
|
}
|
|
3685
3741
|
} catch {
|
|
3686
3742
|
}
|
|
3687
3743
|
try {
|
|
3688
|
-
await
|
|
3744
|
+
await memoryStore({
|
|
3689
3745
|
content: candidate.content,
|
|
3690
3746
|
type: candidate.type,
|
|
3691
3747
|
tags: candidate.tags,
|
|
@@ -3876,9 +3932,9 @@ function humanizeError(message) {
|
|
|
3876
3932
|
}
|
|
3877
3933
|
|
|
3878
3934
|
// src/hints.ts
|
|
3879
|
-
import
|
|
3880
|
-
import
|
|
3881
|
-
import
|
|
3935
|
+
import fs12 from "fs";
|
|
3936
|
+
import path12 from "path";
|
|
3937
|
+
import os11 from "os";
|
|
3882
3938
|
var HINTS = [
|
|
3883
3939
|
{
|
|
3884
3940
|
id: "eval",
|
|
@@ -3916,11 +3972,11 @@ function getHint(state, ctx) {
|
|
|
3916
3972
|
}
|
|
3917
3973
|
return null;
|
|
3918
3974
|
}
|
|
3919
|
-
var HINTS_FILE =
|
|
3975
|
+
var HINTS_FILE = path12.join(os11.homedir(), ".aman-agent", "hints-seen.json");
|
|
3920
3976
|
function loadShownHints() {
|
|
3921
3977
|
try {
|
|
3922
|
-
if (
|
|
3923
|
-
const data = JSON.parse(
|
|
3978
|
+
if (fs12.existsSync(HINTS_FILE)) {
|
|
3979
|
+
const data = JSON.parse(fs12.readFileSync(HINTS_FILE, "utf-8"));
|
|
3924
3980
|
return new Set(Array.isArray(data) ? data : []);
|
|
3925
3981
|
}
|
|
3926
3982
|
} catch {
|
|
@@ -3929,31 +3985,27 @@ function loadShownHints() {
|
|
|
3929
3985
|
}
|
|
3930
3986
|
function saveShownHints(shown) {
|
|
3931
3987
|
try {
|
|
3932
|
-
const dir =
|
|
3933
|
-
|
|
3934
|
-
|
|
3988
|
+
const dir = path12.dirname(HINTS_FILE);
|
|
3989
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
3990
|
+
fs12.writeFileSync(HINTS_FILE, JSON.stringify([...shown]), "utf-8");
|
|
3935
3991
|
} catch {
|
|
3936
3992
|
}
|
|
3937
3993
|
}
|
|
3938
3994
|
|
|
3939
3995
|
// src/agent.ts
|
|
3940
3996
|
marked.use(markedTerminal());
|
|
3941
|
-
async function recallForMessage(input
|
|
3997
|
+
async function recallForMessage(input) {
|
|
3942
3998
|
try {
|
|
3943
|
-
const result = await
|
|
3944
|
-
|
|
3945
|
-
limit: 5,
|
|
3946
|
-
compact: true
|
|
3947
|
-
});
|
|
3948
|
-
if (!result || result.startsWith("Error") || result.includes("No memories found")) {
|
|
3999
|
+
const result = await memoryRecall(input, { limit: 5, compact: true });
|
|
4000
|
+
if (result.total === 0) {
|
|
3949
4001
|
return null;
|
|
3950
4002
|
}
|
|
3951
|
-
const tokenEstimate = Math.round(result.split(/\s+/).filter(Boolean).length * 1.3);
|
|
4003
|
+
const tokenEstimate = result.tokenEstimate ?? Math.round(result.text.split(/\s+/).filter(Boolean).length * 1.3);
|
|
3952
4004
|
return {
|
|
3953
4005
|
text: `
|
|
3954
4006
|
|
|
3955
4007
|
<relevant-memories>
|
|
3956
|
-
${result}
|
|
4008
|
+
${result.text}
|
|
3957
4009
|
</relevant-memories>`,
|
|
3958
4010
|
tokenEstimate
|
|
3959
4011
|
};
|
|
@@ -4124,9 +4176,9 @@ Type a message, ${pc6.dim("/help")} for commands, or ${pc6.dim("/quit")} to exit
|
|
|
4124
4176
|
}
|
|
4125
4177
|
if (cmdResult.exportConversation) {
|
|
4126
4178
|
try {
|
|
4127
|
-
const exportDir =
|
|
4128
|
-
|
|
4129
|
-
const exportPath =
|
|
4179
|
+
const exportDir = path13.join(os12.homedir(), ".aman-agent", "exports");
|
|
4180
|
+
fs13.mkdirSync(exportDir, { recursive: true });
|
|
4181
|
+
const exportPath = path13.join(exportDir, `${sessionId}.md`);
|
|
4130
4182
|
const lines = [
|
|
4131
4183
|
`# Conversation \u2014 ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
4132
4184
|
`**Model:** ${model}`,
|
|
@@ -4140,16 +4192,16 @@ Type a message, ${pc6.dim("/help")} for commands, or ${pc6.dim("/quit")} to exit
|
|
|
4140
4192
|
lines.push(`${label} ${msg.content}`, "");
|
|
4141
4193
|
}
|
|
4142
4194
|
}
|
|
4143
|
-
|
|
4195
|
+
fs13.writeFileSync(exportPath, lines.join("\n"), "utf-8");
|
|
4144
4196
|
console.log(pc6.green(`Exported to ${exportPath}`));
|
|
4145
4197
|
} catch {
|
|
4146
4198
|
console.log(pc6.red("Failed to export conversation."));
|
|
4147
4199
|
}
|
|
4148
4200
|
continue;
|
|
4149
4201
|
}
|
|
4150
|
-
if (cmdResult.saveConversation
|
|
4202
|
+
if (cmdResult.saveConversation) {
|
|
4151
4203
|
try {
|
|
4152
|
-
await saveConversationToMemory(
|
|
4204
|
+
await saveConversationToMemory(messages, sessionId);
|
|
4153
4205
|
console.log(pc6.green("Conversation saved to memory."));
|
|
4154
4206
|
} catch {
|
|
4155
4207
|
console.log(pc6.red("Failed to save conversation."));
|
|
@@ -4266,25 +4318,25 @@ ${knowledgeItem.content}
|
|
|
4266
4318
|
for (const match of filePathMatches) {
|
|
4267
4319
|
let filePath = match[1];
|
|
4268
4320
|
if (filePath.startsWith("~/")) {
|
|
4269
|
-
filePath =
|
|
4321
|
+
filePath = path13.join(os12.homedir(), filePath.slice(2));
|
|
4270
4322
|
}
|
|
4271
|
-
if (!
|
|
4272
|
-
const ext =
|
|
4323
|
+
if (!fs13.existsSync(filePath) || !fs13.statSync(filePath).isFile()) continue;
|
|
4324
|
+
const ext = path13.extname(filePath).toLowerCase();
|
|
4273
4325
|
if (imageExts.has(ext)) {
|
|
4274
4326
|
try {
|
|
4275
|
-
const stat =
|
|
4327
|
+
const stat = fs13.statSync(filePath);
|
|
4276
4328
|
if (stat.size > maxImageBytes) {
|
|
4277
|
-
process.stdout.write(pc6.yellow(` [skipped: ${
|
|
4329
|
+
process.stdout.write(pc6.yellow(` [skipped: ${path13.basename(filePath)} \u2014 exceeds 20MB limit]
|
|
4278
4330
|
`));
|
|
4279
4331
|
continue;
|
|
4280
4332
|
}
|
|
4281
|
-
const data =
|
|
4333
|
+
const data = fs13.readFileSync(filePath).toString("base64");
|
|
4282
4334
|
const mediaType = mimeMap[ext] || "image/png";
|
|
4283
4335
|
imageBlocks.push({
|
|
4284
4336
|
type: "image",
|
|
4285
4337
|
source: { type: "base64", media_type: mediaType, data }
|
|
4286
4338
|
});
|
|
4287
|
-
process.stdout.write(pc6.dim(` [attached image: ${
|
|
4339
|
+
process.stdout.write(pc6.dim(` [attached image: ${path13.basename(filePath)} (${(stat.size / 1024).toFixed(1)}KB)]
|
|
4288
4340
|
`));
|
|
4289
4341
|
} catch {
|
|
4290
4342
|
process.stdout.write(pc6.dim(` [could not read image: ${filePath}]
|
|
@@ -4292,7 +4344,7 @@ ${knowledgeItem.content}
|
|
|
4292
4344
|
}
|
|
4293
4345
|
} else if (textExts.has(ext) || ext === "") {
|
|
4294
4346
|
try {
|
|
4295
|
-
const content =
|
|
4347
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
4296
4348
|
const maxChars = 5e4;
|
|
4297
4349
|
const trimmed = content.length > maxChars ? content.slice(0, maxChars) + `
|
|
4298
4350
|
|
|
@@ -4302,7 +4354,7 @@ ${knowledgeItem.content}
|
|
|
4302
4354
|
<file path="${filePath}" size="${content.length} chars">
|
|
4303
4355
|
${trimmed}
|
|
4304
4356
|
</file>`;
|
|
4305
|
-
process.stdout.write(pc6.dim(` [attached: ${
|
|
4357
|
+
process.stdout.write(pc6.dim(` [attached: ${path13.basename(filePath)} (${(content.length / 1024).toFixed(1)}KB)]
|
|
4306
4358
|
`));
|
|
4307
4359
|
} catch {
|
|
4308
4360
|
process.stdout.write(pc6.dim(` [could not read: ${filePath}]
|
|
@@ -4311,7 +4363,7 @@ ${trimmed}
|
|
|
4311
4363
|
} else if (docExts.has(ext)) {
|
|
4312
4364
|
if (mcpManager) {
|
|
4313
4365
|
try {
|
|
4314
|
-
process.stdout.write(pc6.dim(` [converting: ${
|
|
4366
|
+
process.stdout.write(pc6.dim(` [converting: ${path13.basename(filePath)}...]
|
|
4315
4367
|
`));
|
|
4316
4368
|
const converted = await mcpManager.callTool("doc_convert", { path: filePath });
|
|
4317
4369
|
if (converted && !converted.startsWith("Error") && !converted.includes("Could not convert")) {
|
|
@@ -4320,7 +4372,7 @@ ${trimmed}
|
|
|
4320
4372
|
<file path="${filePath}" format="${ext}">
|
|
4321
4373
|
${converted.slice(0, 5e4)}
|
|
4322
4374
|
</file>`;
|
|
4323
|
-
process.stdout.write(pc6.dim(` [attached: ${
|
|
4375
|
+
process.stdout.write(pc6.dim(` [attached: ${path13.basename(filePath)} (converted from ${ext})]
|
|
4324
4376
|
`));
|
|
4325
4377
|
} else {
|
|
4326
4378
|
textContent += `
|
|
@@ -4332,7 +4384,7 @@ ${converted}
|
|
|
4332
4384
|
`));
|
|
4333
4385
|
}
|
|
4334
4386
|
} catch {
|
|
4335
|
-
process.stdout.write(pc6.dim(` [could not convert: ${
|
|
4387
|
+
process.stdout.write(pc6.dim(` [could not convert: ${path13.basename(filePath)}]
|
|
4336
4388
|
`));
|
|
4337
4389
|
}
|
|
4338
4390
|
} else {
|
|
@@ -4387,11 +4439,11 @@ ${converted}
|
|
|
4387
4439
|
}
|
|
4388
4440
|
let augmentedSystemPrompt = activeSystemPrompt;
|
|
4389
4441
|
let memoryTokens = 0;
|
|
4390
|
-
|
|
4391
|
-
const
|
|
4392
|
-
if (
|
|
4393
|
-
augmentedSystemPrompt = activeSystemPrompt +
|
|
4394
|
-
memoryTokens =
|
|
4442
|
+
{
|
|
4443
|
+
const recall2 = await recallForMessage(input);
|
|
4444
|
+
if (recall2) {
|
|
4445
|
+
augmentedSystemPrompt = activeSystemPrompt + recall2.text;
|
|
4446
|
+
memoryTokens = recall2.tokenEstimate;
|
|
4395
4447
|
}
|
|
4396
4448
|
}
|
|
4397
4449
|
const userTurnCount = messages.filter((m) => m.role === "user").length;
|
|
@@ -4493,12 +4545,10 @@ ${result2.response}` : `[${input2.profile}] failed: ${result2.error}`;
|
|
|
4493
4545
|
const result = await mcpManager.callTool(toolUse.name, toolUse.input);
|
|
4494
4546
|
const skipLogging = ["memory_log", "memory_recall", "memory_context", "memory_detail", "reminder_check"].includes(toolUse.name);
|
|
4495
4547
|
if (!skipLogging) {
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
}).catch(() => {
|
|
4501
|
-
});
|
|
4548
|
+
try {
|
|
4549
|
+
memoryLog(sessionId, "system", `[tool:${toolUse.name}] input=${JSON.stringify(toolUse.input).slice(0, 500)} result=${result.slice(0, 500)}`);
|
|
4550
|
+
} catch {
|
|
4551
|
+
}
|
|
4502
4552
|
}
|
|
4503
4553
|
return {
|
|
4504
4554
|
type: "tool_result",
|
|
@@ -4523,14 +4573,13 @@ ${result2.response}` : `[${input2.profile}] failed: ${result2.error}`;
|
|
|
4523
4573
|
const footerDivider = "\u2500".repeat(Math.min(process.stdout.columns || 60, 60) - footer.length - 1);
|
|
4524
4574
|
process.stdout.write(pc6.dim(` ${footerDivider}${footer}
|
|
4525
4575
|
`));
|
|
4526
|
-
if (
|
|
4576
|
+
if (hooksConfig?.extractMemories) {
|
|
4527
4577
|
const assistantText = typeof response.message.content === "string" ? response.message.content : response.message.content.filter((b) => b.type === "text").map((b) => "text" in b ? b.text : "").join("");
|
|
4528
4578
|
if (assistantText) {
|
|
4529
4579
|
const count = await extractMemories(
|
|
4530
4580
|
input,
|
|
4531
4581
|
assistantText,
|
|
4532
4582
|
client,
|
|
4533
|
-
mcpManager,
|
|
4534
4583
|
extractorState
|
|
4535
4584
|
);
|
|
4536
4585
|
if (count > 0) {
|
|
@@ -4543,7 +4592,7 @@ ${result2.response}` : `[${input2.profile}] failed: ${result2.error}`;
|
|
|
4543
4592
|
}
|
|
4544
4593
|
if (hooksConfig?.featureHints) {
|
|
4545
4594
|
hintState.turnCount++;
|
|
4546
|
-
const hasWorkflows =
|
|
4595
|
+
const hasWorkflows = fs13.existsSync(path13.join(os12.homedir(), ".aflow", "flow.md"));
|
|
4547
4596
|
const memoryCount = memoryTokens > 0 ? Math.floor(memoryTokens / 5) : 0;
|
|
4548
4597
|
const hint = getHint(hintState, { hasWorkflows, memoryCount });
|
|
4549
4598
|
if (hint) {
|
|
@@ -4560,16 +4609,12 @@ ${result2.response}` : `[${input2.profile}] failed: ${result2.error}`;
|
|
|
4560
4609
|
}
|
|
4561
4610
|
}
|
|
4562
4611
|
}
|
|
4563
|
-
async function saveConversationToMemory(
|
|
4612
|
+
async function saveConversationToMemory(messages, sessionId) {
|
|
4564
4613
|
const recentMessages = messages.slice(-50);
|
|
4565
4614
|
for (const msg of recentMessages) {
|
|
4566
4615
|
if (typeof msg.content !== "string") continue;
|
|
4567
4616
|
try {
|
|
4568
|
-
|
|
4569
|
-
session_id: sessionId,
|
|
4570
|
-
role: msg.role,
|
|
4571
|
-
content: msg.content.slice(0, 5e3)
|
|
4572
|
-
});
|
|
4617
|
+
memoryLog(sessionId, msg.role, msg.content.slice(0, 5e3));
|
|
4573
4618
|
} catch (err) {
|
|
4574
4619
|
log.debug("agent", "memory_log write failed", err);
|
|
4575
4620
|
}
|
|
@@ -4577,9 +4622,9 @@ async function saveConversationToMemory(mcpManager, messages, sessionId) {
|
|
|
4577
4622
|
}
|
|
4578
4623
|
|
|
4579
4624
|
// src/index.ts
|
|
4580
|
-
import
|
|
4581
|
-
import
|
|
4582
|
-
import
|
|
4625
|
+
import fs14 from "fs";
|
|
4626
|
+
import path14 from "path";
|
|
4627
|
+
import os13 from "os";
|
|
4583
4628
|
|
|
4584
4629
|
// src/presets.ts
|
|
4585
4630
|
var PRESETS = {
|
|
@@ -4688,9 +4733,9 @@ ${wfSections}`;
|
|
|
4688
4733
|
|
|
4689
4734
|
// src/index.ts
|
|
4690
4735
|
async function autoDetectConfig() {
|
|
4691
|
-
const reconfigMarker =
|
|
4692
|
-
if (
|
|
4693
|
-
|
|
4736
|
+
const reconfigMarker = path14.join(os13.homedir(), ".aman-agent", ".reconfig");
|
|
4737
|
+
if (fs14.existsSync(reconfigMarker)) {
|
|
4738
|
+
fs14.unlinkSync(reconfigMarker);
|
|
4694
4739
|
return null;
|
|
4695
4740
|
}
|
|
4696
4741
|
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
@@ -4719,11 +4764,11 @@ async function autoDetectConfig() {
|
|
|
4719
4764
|
return null;
|
|
4720
4765
|
}
|
|
4721
4766
|
function bootstrapEcosystem() {
|
|
4722
|
-
const home2 =
|
|
4723
|
-
const corePath =
|
|
4724
|
-
if (
|
|
4725
|
-
|
|
4726
|
-
|
|
4767
|
+
const home2 = os13.homedir();
|
|
4768
|
+
const corePath = path14.join(home2, ".acore", "core.md");
|
|
4769
|
+
if (fs14.existsSync(corePath)) return false;
|
|
4770
|
+
fs14.mkdirSync(path14.join(home2, ".acore"), { recursive: true });
|
|
4771
|
+
fs14.writeFileSync(corePath, [
|
|
4727
4772
|
"# Aman",
|
|
4728
4773
|
"",
|
|
4729
4774
|
"## Personality",
|
|
@@ -4735,11 +4780,11 @@ function bootstrapEcosystem() {
|
|
|
4735
4780
|
"## Session",
|
|
4736
4781
|
"_New companion \u2014 no prior sessions._"
|
|
4737
4782
|
].join("\n"), "utf-8");
|
|
4738
|
-
const rulesDir =
|
|
4739
|
-
const rulesPath =
|
|
4740
|
-
if (!
|
|
4741
|
-
|
|
4742
|
-
|
|
4783
|
+
const rulesDir = path14.join(home2, ".arules");
|
|
4784
|
+
const rulesPath = path14.join(rulesDir, "rules.md");
|
|
4785
|
+
if (!fs14.existsSync(rulesPath)) {
|
|
4786
|
+
fs14.mkdirSync(rulesDir, { recursive: true });
|
|
4787
|
+
fs14.writeFileSync(rulesPath, [
|
|
4743
4788
|
"# Guardrails",
|
|
4744
4789
|
"",
|
|
4745
4790
|
"## safety",
|
|
@@ -4881,11 +4926,11 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
4881
4926
|
}
|
|
4882
4927
|
}
|
|
4883
4928
|
const aiName = getProfileAiName(profile);
|
|
4929
|
+
await initMemory();
|
|
4884
4930
|
const mcpManager = new McpManager();
|
|
4885
4931
|
const mcpSpinner = p2.spinner();
|
|
4886
4932
|
mcpSpinner.start("Connecting to MCP servers");
|
|
4887
4933
|
await mcpManager.connect("aman", "npx", ["-y", "@aman_asmuei/aman-mcp"]);
|
|
4888
|
-
await mcpManager.connect("amem", "npx", ["-y", "@aman_asmuei/amem"]);
|
|
4889
4934
|
if (config.mcpServers) {
|
|
4890
4935
|
for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
|
|
4891
4936
|
if (name === "aman" || name === "amem") continue;
|
|
@@ -4896,25 +4941,16 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
4896
4941
|
mcpSpinner.stop("MCP connected");
|
|
4897
4942
|
if (mcpTools.length > 0) {
|
|
4898
4943
|
p2.log.success(`${mcpTools.length} MCP tools available`);
|
|
4899
|
-
|
|
4944
|
+
{
|
|
4900
4945
|
const memSpinner = p2.spinner();
|
|
4901
4946
|
memSpinner.start("Consolidating memory");
|
|
4902
4947
|
try {
|
|
4903
|
-
const
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
p2.log.info(
|
|
4910
|
-
`Memory health: ${report.healthScore ?? "?"}% ` + pc7.dim(`(merged ${report.merged}, pruned ${report.pruned}, promoted ${report.promoted})`)
|
|
4911
|
-
);
|
|
4912
|
-
}
|
|
4913
|
-
} catch {
|
|
4914
|
-
memSpinner.stop("Memory consolidated");
|
|
4915
|
-
}
|
|
4916
|
-
} else {
|
|
4917
|
-
memSpinner.stop("Memory consolidated");
|
|
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
|
+
);
|
|
4918
4954
|
}
|
|
4919
4955
|
} catch {
|
|
4920
4956
|
memSpinner.stop("Memory consolidation skipped");
|
|
@@ -4971,19 +5007,19 @@ program.command("init").description("Set up your AI companion with a guided wiza
|
|
|
4971
5007
|
});
|
|
4972
5008
|
if (p2.isCancel(preset)) process.exit(0);
|
|
4973
5009
|
const result = applyPreset(preset, name || "Aman");
|
|
4974
|
-
const home2 =
|
|
4975
|
-
|
|
4976
|
-
|
|
5010
|
+
const home2 = os13.homedir();
|
|
5011
|
+
fs14.mkdirSync(path14.join(home2, ".acore"), { recursive: true });
|
|
5012
|
+
fs14.writeFileSync(path14.join(home2, ".acore", "core.md"), result.coreMd, "utf-8");
|
|
4977
5013
|
p2.log.success(`Identity created \u2014 ${PRESETS[preset].identity.personality.split(".")[0].toLowerCase()}`);
|
|
4978
5014
|
if (result.rulesMd) {
|
|
4979
|
-
|
|
4980
|
-
|
|
5015
|
+
fs14.mkdirSync(path14.join(home2, ".arules"), { recursive: true });
|
|
5016
|
+
fs14.writeFileSync(path14.join(home2, ".arules", "rules.md"), result.rulesMd, "utf-8");
|
|
4981
5017
|
const ruleCount = (result.rulesMd.match(/^- /gm) || []).length;
|
|
4982
5018
|
p2.log.success(`${ruleCount} rules set`);
|
|
4983
5019
|
}
|
|
4984
5020
|
if (result.flowMd) {
|
|
4985
|
-
|
|
4986
|
-
|
|
5021
|
+
fs14.mkdirSync(path14.join(home2, ".aflow"), { recursive: true });
|
|
5022
|
+
fs14.writeFileSync(path14.join(home2, ".aflow", "flow.md"), result.flowMd, "utf-8");
|
|
4987
5023
|
const wfCount = (result.flowMd.match(/^## /gm) || []).length;
|
|
4988
5024
|
p2.log.success(`${wfCount} workflow${wfCount > 1 ? "s" : ""} added`);
|
|
4989
5025
|
}
|