@aman_asmuei/aman-agent 0.31.0 → 0.32.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/README.md +17 -8
- package/dist/delegate.js +61 -49
- package/dist/delegate.js.map +1 -1
- package/dist/index.js +481 -370
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -9,22 +9,22 @@ var __export = (target, all) => {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
// src/logger.ts
|
|
12
|
-
import
|
|
13
|
-
import
|
|
12
|
+
import fs5 from "fs";
|
|
13
|
+
import path5 from "path";
|
|
14
14
|
import os4 from "os";
|
|
15
15
|
function ensureDir() {
|
|
16
|
-
if (!
|
|
17
|
-
|
|
16
|
+
if (!fs5.existsSync(LOG_DIR)) {
|
|
17
|
+
fs5.mkdirSync(LOG_DIR, { recursive: true });
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
function maybeRotate() {
|
|
21
21
|
try {
|
|
22
|
-
if (!
|
|
23
|
-
const stat =
|
|
22
|
+
if (!fs5.existsSync(LOG_PATH)) return;
|
|
23
|
+
const stat = fs5.statSync(LOG_PATH);
|
|
24
24
|
if (stat.size >= MAX_LOG_SIZE) {
|
|
25
25
|
const backupPath = LOG_PATH + ".1";
|
|
26
|
-
if (
|
|
27
|
-
|
|
26
|
+
if (fs5.existsSync(backupPath)) fs5.unlinkSync(backupPath);
|
|
27
|
+
fs5.renameSync(LOG_PATH, backupPath);
|
|
28
28
|
}
|
|
29
29
|
} catch {
|
|
30
30
|
}
|
|
@@ -42,7 +42,7 @@ function write(level, module, message, data) {
|
|
|
42
42
|
if (data !== void 0) {
|
|
43
43
|
entry.data = data instanceof Error ? data.message : String(data);
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
fs5.appendFileSync(LOG_PATH, JSON.stringify(entry) + "\n");
|
|
46
46
|
} catch {
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -50,8 +50,8 @@ var LOG_DIR, LOG_PATH, MAX_LOG_SIZE, log;
|
|
|
50
50
|
var init_logger = __esm({
|
|
51
51
|
"src/logger.ts"() {
|
|
52
52
|
"use strict";
|
|
53
|
-
LOG_DIR =
|
|
54
|
-
LOG_PATH =
|
|
53
|
+
LOG_DIR = path5.join(os4.homedir(), ".aman-agent");
|
|
54
|
+
LOG_PATH = path5.join(LOG_DIR, "debug.log");
|
|
55
55
|
MAX_LOG_SIZE = 1048576;
|
|
56
56
|
log = {
|
|
57
57
|
debug: (module, message, data) => write("debug", module, message, data),
|
|
@@ -73,11 +73,11 @@ __export(user_model_exports, {
|
|
|
73
73
|
predictBurnout: () => predictBurnout,
|
|
74
74
|
saveUserModel: () => saveUserModel
|
|
75
75
|
});
|
|
76
|
-
import
|
|
77
|
-
import
|
|
76
|
+
import fs14 from "fs/promises";
|
|
77
|
+
import path14 from "path";
|
|
78
78
|
import os12 from "os";
|
|
79
79
|
function defaultModelPath() {
|
|
80
|
-
return
|
|
80
|
+
return path14.join(os12.homedir(), ".acore", "user-model.json");
|
|
81
81
|
}
|
|
82
82
|
function createEmptyModel() {
|
|
83
83
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -109,7 +109,7 @@ function emptyProfile() {
|
|
|
109
109
|
async function loadUserModel(filePath) {
|
|
110
110
|
const fp = filePath ?? defaultModelPath();
|
|
111
111
|
try {
|
|
112
|
-
const raw = await
|
|
112
|
+
const raw = await fs14.readFile(fp, "utf-8");
|
|
113
113
|
const parsed = JSON.parse(raw);
|
|
114
114
|
if (parsed?.version !== 1) return null;
|
|
115
115
|
return parsed;
|
|
@@ -119,11 +119,11 @@ async function loadUserModel(filePath) {
|
|
|
119
119
|
}
|
|
120
120
|
async function saveUserModel(model, filePath) {
|
|
121
121
|
const fp = filePath ?? defaultModelPath();
|
|
122
|
-
const dir =
|
|
123
|
-
await
|
|
122
|
+
const dir = path14.dirname(fp);
|
|
123
|
+
await fs14.mkdir(dir, { recursive: true });
|
|
124
124
|
const tmp = fp + `.tmp-${Date.now()}`;
|
|
125
|
-
await
|
|
126
|
-
await
|
|
125
|
+
await fs14.writeFile(tmp, JSON.stringify(model, null, 2), "utf-8");
|
|
126
|
+
await fs14.rename(tmp, fp);
|
|
127
127
|
}
|
|
128
128
|
function aggregateSession(model, snapshot) {
|
|
129
129
|
const sessions = [...model.sessions, snapshot];
|
|
@@ -386,21 +386,21 @@ var init_user_model = __esm({
|
|
|
386
386
|
});
|
|
387
387
|
|
|
388
388
|
// src/server/registry.ts
|
|
389
|
-
import
|
|
390
|
-
import
|
|
389
|
+
import fs16 from "fs/promises";
|
|
390
|
+
import path16 from "path";
|
|
391
391
|
import os14 from "os";
|
|
392
392
|
function amanAgentHome() {
|
|
393
|
-
return process.env.AMAN_AGENT_HOME ||
|
|
393
|
+
return process.env.AMAN_AGENT_HOME || path16.join(os14.homedir(), ".aman-agent");
|
|
394
394
|
}
|
|
395
395
|
function registryPath() {
|
|
396
|
-
return
|
|
396
|
+
return path16.join(amanAgentHome(), "registry.json");
|
|
397
397
|
}
|
|
398
398
|
async function ensureHome() {
|
|
399
|
-
await
|
|
399
|
+
await fs16.mkdir(amanAgentHome(), { recursive: true });
|
|
400
400
|
}
|
|
401
401
|
async function readRaw() {
|
|
402
402
|
try {
|
|
403
|
-
const buf = await
|
|
403
|
+
const buf = await fs16.readFile(registryPath(), "utf-8");
|
|
404
404
|
const parsed = JSON.parse(buf);
|
|
405
405
|
return Array.isArray(parsed) ? parsed : [];
|
|
406
406
|
} catch (err) {
|
|
@@ -414,10 +414,10 @@ async function readRaw() {
|
|
|
414
414
|
async function writeAtomic(entries) {
|
|
415
415
|
await ensureHome();
|
|
416
416
|
const tmp = registryPath() + ".tmp";
|
|
417
|
-
await
|
|
418
|
-
await
|
|
417
|
+
await fs16.writeFile(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
418
|
+
await fs16.rename(tmp, registryPath());
|
|
419
419
|
try {
|
|
420
|
-
await
|
|
420
|
+
await fs16.chmod(registryPath(), 384);
|
|
421
421
|
} catch {
|
|
422
422
|
}
|
|
423
423
|
}
|
|
@@ -620,8 +620,26 @@ var DEFAULT_HOOKS = {
|
|
|
620
620
|
featureHints: true,
|
|
621
621
|
personalityAdapt: true
|
|
622
622
|
};
|
|
623
|
+
function homeDir() {
|
|
624
|
+
return process.env.AMAN_HOME || process.env.AMAN_AGENT_HOME || path.join(os.homedir(), ".aman-agent");
|
|
625
|
+
}
|
|
626
|
+
function identityDir() {
|
|
627
|
+
return path.join(homeDir(), "identity");
|
|
628
|
+
}
|
|
629
|
+
function rulesDir() {
|
|
630
|
+
return path.join(homeDir(), "rules");
|
|
631
|
+
}
|
|
632
|
+
function memoryDir() {
|
|
633
|
+
return path.join(homeDir(), "memory");
|
|
634
|
+
}
|
|
635
|
+
function workflowsDir() {
|
|
636
|
+
return path.join(homeDir(), "workflows");
|
|
637
|
+
}
|
|
638
|
+
function skillsDir() {
|
|
639
|
+
return path.join(homeDir(), "skills");
|
|
640
|
+
}
|
|
623
641
|
function configDir() {
|
|
624
|
-
return
|
|
642
|
+
return homeDir();
|
|
625
643
|
}
|
|
626
644
|
function configPath() {
|
|
627
645
|
return path.join(configDir(), "config.json");
|
|
@@ -646,9 +664,40 @@ function saveConfig(config) {
|
|
|
646
664
|
);
|
|
647
665
|
}
|
|
648
666
|
|
|
667
|
+
// src/migrate.ts
|
|
668
|
+
import fs2 from "fs";
|
|
669
|
+
import path2 from "path";
|
|
670
|
+
import os2 from "os";
|
|
671
|
+
var MIGRATION_MAP = [
|
|
672
|
+
{ oldName: ".acore", newSubdir: "identity" },
|
|
673
|
+
{ oldName: ".arules", newSubdir: "rules" },
|
|
674
|
+
{ oldName: ".aflow", newSubdir: "workflows" },
|
|
675
|
+
{ oldName: ".askill", newSubdir: "skills" },
|
|
676
|
+
{ oldName: ".amem", newSubdir: "memory" },
|
|
677
|
+
{ oldName: ".aeval", newSubdir: "eval" }
|
|
678
|
+
];
|
|
679
|
+
function migrateIfNeeded() {
|
|
680
|
+
const home2 = os2.homedir();
|
|
681
|
+
const target = homeDir();
|
|
682
|
+
const migrated = [];
|
|
683
|
+
for (const { oldName, newSubdir } of MIGRATION_MAP) {
|
|
684
|
+
const oldDir = path2.join(home2, oldName);
|
|
685
|
+
const newDir = path2.join(target, newSubdir);
|
|
686
|
+
if (!fs2.existsSync(oldDir)) continue;
|
|
687
|
+
if (fs2.existsSync(newDir) && fs2.readdirSync(newDir).length > 0) continue;
|
|
688
|
+
fs2.mkdirSync(newDir, { recursive: true });
|
|
689
|
+
for (const entry of fs2.readdirSync(oldDir)) {
|
|
690
|
+
fs2.renameSync(path2.join(oldDir, entry), path2.join(newDir, entry));
|
|
691
|
+
}
|
|
692
|
+
fs2.rmSync(oldDir, { recursive: true, force: true });
|
|
693
|
+
migrated.push(newSubdir);
|
|
694
|
+
}
|
|
695
|
+
return { migrated };
|
|
696
|
+
}
|
|
697
|
+
|
|
649
698
|
// src/prompt.ts
|
|
650
|
-
import
|
|
651
|
-
import
|
|
699
|
+
import fs4 from "fs";
|
|
700
|
+
import path4 from "path";
|
|
652
701
|
import os3 from "os";
|
|
653
702
|
|
|
654
703
|
// src/token-budget.ts
|
|
@@ -705,17 +754,16 @@ function buildBudgetedPrompt(components, maxTokens = 8e3) {
|
|
|
705
754
|
}
|
|
706
755
|
|
|
707
756
|
// src/user-identity.ts
|
|
708
|
-
import
|
|
709
|
-
import
|
|
710
|
-
|
|
711
|
-
var USER_FILE = path2.join(os2.homedir(), ".acore", "user.md");
|
|
757
|
+
import fs3 from "fs";
|
|
758
|
+
import path3 from "path";
|
|
759
|
+
var USER_FILE = path3.join(identityDir(), "user.md");
|
|
712
760
|
function hasUserIdentity() {
|
|
713
|
-
return
|
|
761
|
+
return fs3.existsSync(USER_FILE);
|
|
714
762
|
}
|
|
715
763
|
function loadUserIdentity() {
|
|
716
|
-
if (!
|
|
764
|
+
if (!fs3.existsSync(USER_FILE)) return null;
|
|
717
765
|
try {
|
|
718
|
-
const content =
|
|
766
|
+
const content = fs3.readFileSync(USER_FILE, "utf-8");
|
|
719
767
|
const get = (key) => {
|
|
720
768
|
const match = content.match(new RegExp(`^- ${key}:\\s*(.+)$`, "m"));
|
|
721
769
|
return match?.[1]?.trim() ?? "";
|
|
@@ -746,8 +794,8 @@ function loadUserIdentity() {
|
|
|
746
794
|
}
|
|
747
795
|
}
|
|
748
796
|
function saveUserIdentity(user) {
|
|
749
|
-
const dir =
|
|
750
|
-
if (!
|
|
797
|
+
const dir = path3.dirname(USER_FILE);
|
|
798
|
+
if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
|
|
751
799
|
const lines = [
|
|
752
800
|
"# User Profile",
|
|
753
801
|
"",
|
|
@@ -772,7 +820,7 @@ function saveUserIdentity(user) {
|
|
|
772
820
|
`- Created: ${user.createdAt}`,
|
|
773
821
|
`- Updated: ${user.updatedAt}`
|
|
774
822
|
);
|
|
775
|
-
|
|
823
|
+
fs3.writeFileSync(USER_FILE, lines.join("\n") + "\n", "utf-8");
|
|
776
824
|
}
|
|
777
825
|
function formatUserContext(user) {
|
|
778
826
|
const parts = [
|
|
@@ -834,19 +882,19 @@ var ECOSYSTEM_FILES = [
|
|
|
834
882
|
];
|
|
835
883
|
function resolveLayerPath(entry, home2, profile) {
|
|
836
884
|
if (profile && entry.profileOverridable) {
|
|
837
|
-
const profilePath =
|
|
838
|
-
if (
|
|
885
|
+
const profilePath = path4.join(home2, ".acore", "profiles", profile, entry.file);
|
|
886
|
+
if (fs4.existsSync(profilePath)) return profilePath;
|
|
839
887
|
if (entry.name === "guardrails") {
|
|
840
|
-
const altPath =
|
|
841
|
-
if (
|
|
888
|
+
const altPath = path4.join(home2, ".acore", "profiles", profile, "rules.md");
|
|
889
|
+
if (fs4.existsSync(altPath)) return altPath;
|
|
842
890
|
}
|
|
843
891
|
if (entry.name === "skills") {
|
|
844
|
-
const altPath =
|
|
845
|
-
if (
|
|
892
|
+
const altPath = path4.join(home2, ".acore", "profiles", profile, "skills.md");
|
|
893
|
+
if (fs4.existsSync(altPath)) return altPath;
|
|
846
894
|
}
|
|
847
895
|
}
|
|
848
|
-
const globalPath =
|
|
849
|
-
if (
|
|
896
|
+
const globalPath = path4.join(home2, entry.dir, entry.file);
|
|
897
|
+
if (fs4.existsSync(globalPath)) return globalPath;
|
|
850
898
|
return null;
|
|
851
899
|
}
|
|
852
900
|
function assembleSystemPrompt(maxTokens, profile) {
|
|
@@ -855,7 +903,7 @@ function assembleSystemPrompt(maxTokens, profile) {
|
|
|
855
903
|
for (const entry of ECOSYSTEM_FILES) {
|
|
856
904
|
const filePath = resolveLayerPath(entry, home2, profile);
|
|
857
905
|
if (filePath) {
|
|
858
|
-
const content =
|
|
906
|
+
const content = fs4.readFileSync(filePath, "utf-8").trim();
|
|
859
907
|
components.push({
|
|
860
908
|
name: entry.name,
|
|
861
909
|
content,
|
|
@@ -863,9 +911,9 @@ function assembleSystemPrompt(maxTokens, profile) {
|
|
|
863
911
|
});
|
|
864
912
|
}
|
|
865
913
|
}
|
|
866
|
-
const contextPath =
|
|
867
|
-
if (
|
|
868
|
-
const content =
|
|
914
|
+
const contextPath = path4.join(process.cwd(), ".acore", "context.md");
|
|
915
|
+
if (fs4.existsSync(contextPath)) {
|
|
916
|
+
const content = fs4.readFileSync(contextPath, "utf-8").trim();
|
|
869
917
|
components.push({
|
|
870
918
|
name: "context",
|
|
871
919
|
content,
|
|
@@ -891,14 +939,14 @@ function assembleSystemPrompt(maxTokens, profile) {
|
|
|
891
939
|
};
|
|
892
940
|
}
|
|
893
941
|
function listProfiles() {
|
|
894
|
-
const profilesDir =
|
|
895
|
-
if (!
|
|
942
|
+
const profilesDir = path4.join(os3.homedir(), ".acore", "profiles");
|
|
943
|
+
if (!fs4.existsSync(profilesDir)) return [];
|
|
896
944
|
const profiles = [];
|
|
897
|
-
for (const entry of
|
|
945
|
+
for (const entry of fs4.readdirSync(profilesDir, { withFileTypes: true })) {
|
|
898
946
|
if (!entry.isDirectory()) continue;
|
|
899
|
-
const corePath =
|
|
900
|
-
if (!
|
|
901
|
-
const content =
|
|
947
|
+
const corePath = path4.join(profilesDir, entry.name, "core.md");
|
|
948
|
+
if (!fs4.existsSync(corePath)) continue;
|
|
949
|
+
const content = fs4.readFileSync(corePath, "utf-8");
|
|
902
950
|
const nameMatch = content.match(/^# (.+)/m);
|
|
903
951
|
const personalityMatch = content.match(/- Personality:\s*(.+)/);
|
|
904
952
|
profiles.push({
|
|
@@ -913,13 +961,13 @@ function getProfileAiName(profile) {
|
|
|
913
961
|
const home2 = os3.homedir();
|
|
914
962
|
let corePath;
|
|
915
963
|
if (profile) {
|
|
916
|
-
const profileCorePath =
|
|
917
|
-
corePath =
|
|
964
|
+
const profileCorePath = path4.join(home2, ".acore", "profiles", profile, "core.md");
|
|
965
|
+
corePath = fs4.existsSync(profileCorePath) ? profileCorePath : path4.join(home2, ".acore", "core.md");
|
|
918
966
|
} else {
|
|
919
|
-
corePath =
|
|
967
|
+
corePath = path4.join(home2, ".acore", "core.md");
|
|
920
968
|
}
|
|
921
|
-
if (!
|
|
922
|
-
const content =
|
|
969
|
+
if (!fs4.existsSync(corePath)) return "Assistant";
|
|
970
|
+
const content = fs4.readFileSync(corePath, "utf-8");
|
|
923
971
|
const match = content.match(/^# (.+)$/m);
|
|
924
972
|
return match?.[1]?.trim() || "Assistant";
|
|
925
973
|
}
|
|
@@ -1976,8 +2024,8 @@ var McpManager = class {
|
|
|
1976
2024
|
|
|
1977
2025
|
// src/agent.ts
|
|
1978
2026
|
import * as readline from "readline";
|
|
1979
|
-
import
|
|
1980
|
-
import
|
|
2027
|
+
import fs23 from "fs";
|
|
2028
|
+
import path23 from "path";
|
|
1981
2029
|
import os21 from "os";
|
|
1982
2030
|
import pc7 from "picocolors";
|
|
1983
2031
|
import { marked } from "marked";
|
|
@@ -1985,15 +2033,15 @@ import { markedTerminal } from "marked-terminal";
|
|
|
1985
2033
|
import logUpdate from "log-update";
|
|
1986
2034
|
|
|
1987
2035
|
// src/commands.ts
|
|
1988
|
-
import
|
|
1989
|
-
import
|
|
2036
|
+
import fs20 from "fs";
|
|
2037
|
+
import path20 from "path";
|
|
1990
2038
|
import os18 from "os";
|
|
1991
2039
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
1992
2040
|
import pc6 from "picocolors";
|
|
1993
2041
|
|
|
1994
2042
|
// src/layers/parsers.ts
|
|
1995
|
-
import
|
|
1996
|
-
import
|
|
2043
|
+
import fs6 from "fs";
|
|
2044
|
+
import path6 from "path";
|
|
1997
2045
|
import os5 from "os";
|
|
1998
2046
|
var home = os5.homedir();
|
|
1999
2047
|
var LAYER_FILES = [
|
|
@@ -2031,11 +2079,11 @@ function getLayerSummary(name, content) {
|
|
|
2031
2079
|
}
|
|
2032
2080
|
function getEcosystemStatus(mcpToolCount, amemConnected) {
|
|
2033
2081
|
const layers = LAYER_FILES.map((entry) => {
|
|
2034
|
-
const filePath =
|
|
2035
|
-
const exists =
|
|
2082
|
+
const filePath = path6.join(home, entry.dir, entry.file);
|
|
2083
|
+
const exists = fs6.existsSync(filePath);
|
|
2036
2084
|
let summary = "not configured";
|
|
2037
2085
|
if (exists) {
|
|
2038
|
-
const content =
|
|
2086
|
+
const content = fs6.readFileSync(filePath, "utf-8");
|
|
2039
2087
|
summary = getLayerSummary(entry.name, content);
|
|
2040
2088
|
}
|
|
2041
2089
|
return { name: entry.name, exists, path: filePath, summary };
|
|
@@ -2073,25 +2121,25 @@ import {
|
|
|
2073
2121
|
importFromTeam,
|
|
2074
2122
|
syncToCopilot
|
|
2075
2123
|
} from "@aman_asmuei/amem-core";
|
|
2076
|
-
import
|
|
2124
|
+
import path7 from "path";
|
|
2077
2125
|
import os6 from "os";
|
|
2078
|
-
import
|
|
2126
|
+
import fs7 from "fs";
|
|
2079
2127
|
var db = null;
|
|
2080
2128
|
var currentProject = "global";
|
|
2081
2129
|
async function initMemory(project) {
|
|
2082
2130
|
if (db) return db;
|
|
2083
|
-
const amemDir = process.env.AMEM_DIR ??
|
|
2084
|
-
if (!
|
|
2085
|
-
const dbPath = process.env.AMEM_DB ??
|
|
2131
|
+
const amemDir = process.env.AMEM_DIR ?? path7.join(os6.homedir(), ".amem");
|
|
2132
|
+
if (!fs7.existsSync(amemDir)) fs7.mkdirSync(amemDir, { recursive: true });
|
|
2133
|
+
const dbPath = process.env.AMEM_DB ?? path7.join(amemDir, "memory.db");
|
|
2086
2134
|
try {
|
|
2087
2135
|
db = createDatabase(dbPath);
|
|
2088
2136
|
} catch (err) {
|
|
2089
2137
|
const backupPath = `${dbPath}.corrupt.${Date.now()}`;
|
|
2090
2138
|
try {
|
|
2091
|
-
if (
|
|
2092
|
-
|
|
2093
|
-
if (
|
|
2094
|
-
if (
|
|
2139
|
+
if (fs7.existsSync(dbPath)) {
|
|
2140
|
+
fs7.renameSync(dbPath, backupPath);
|
|
2141
|
+
if (fs7.existsSync(`${dbPath}-wal`)) fs7.unlinkSync(`${dbPath}-wal`);
|
|
2142
|
+
if (fs7.existsSync(`${dbPath}-shm`)) fs7.unlinkSync(`${dbPath}-shm`);
|
|
2095
2143
|
console.error(`[amem] Database corrupted \u2014 backed up to ${backupPath}`);
|
|
2096
2144
|
console.error("[amem] Creating fresh database. Previous memories are in the backup file.");
|
|
2097
2145
|
db = createDatabase(dbPath);
|
|
@@ -2240,7 +2288,7 @@ async function memoryRepair(opts = {}) {
|
|
|
2240
2288
|
actions: diag.issues.map((issue) => `Would fix: ${issue.suggestion}`)
|
|
2241
2289
|
};
|
|
2242
2290
|
}
|
|
2243
|
-
const dbPath = process.env.AMEM_DB ??
|
|
2291
|
+
const dbPath = process.env.AMEM_DB ?? path7.join(os6.homedir(), ".amem", "memory.db");
|
|
2244
2292
|
const result = repairDatabase(dbPath);
|
|
2245
2293
|
return {
|
|
2246
2294
|
dryRun: false,
|
|
@@ -2336,8 +2384,8 @@ async function memorySync(action, opts = {}) {
|
|
|
2336
2384
|
}
|
|
2337
2385
|
|
|
2338
2386
|
// src/profile-templates.ts
|
|
2339
|
-
import
|
|
2340
|
-
import
|
|
2387
|
+
import fs8 from "fs";
|
|
2388
|
+
import path8 from "path";
|
|
2341
2389
|
import os7 from "os";
|
|
2342
2390
|
var BUILT_IN_PROFILES = [
|
|
2343
2391
|
{
|
|
@@ -2431,9 +2479,9 @@ var BUILT_IN_PROFILES = [
|
|
|
2431
2479
|
function installProfileTemplate(templateName, userName) {
|
|
2432
2480
|
const template = BUILT_IN_PROFILES.find((t) => t.name === templateName);
|
|
2433
2481
|
if (!template) return null;
|
|
2434
|
-
const profileDir =
|
|
2435
|
-
if (
|
|
2436
|
-
|
|
2482
|
+
const profileDir = path8.join(os7.homedir(), ".acore", "profiles", template.name);
|
|
2483
|
+
if (fs8.existsSync(profileDir)) return `Profile already exists: ${template.name}`;
|
|
2484
|
+
fs8.mkdirSync(profileDir, { recursive: true });
|
|
2437
2485
|
let core = template.core;
|
|
2438
2486
|
if (userName) {
|
|
2439
2487
|
core += `
|
|
@@ -2447,12 +2495,12 @@ function installProfileTemplate(templateName, userName) {
|
|
|
2447
2495
|
- Detail level: balanced
|
|
2448
2496
|
`;
|
|
2449
2497
|
}
|
|
2450
|
-
|
|
2498
|
+
fs8.writeFileSync(path8.join(profileDir, "core.md"), core, "utf-8");
|
|
2451
2499
|
if (template.rules) {
|
|
2452
|
-
|
|
2500
|
+
fs8.writeFileSync(path8.join(profileDir, "rules.md"), template.rules, "utf-8");
|
|
2453
2501
|
}
|
|
2454
2502
|
if (template.skills) {
|
|
2455
|
-
|
|
2503
|
+
fs8.writeFileSync(path8.join(profileDir, "skills.md"), template.skills, "utf-8");
|
|
2456
2504
|
}
|
|
2457
2505
|
return null;
|
|
2458
2506
|
}
|
|
@@ -2463,21 +2511,21 @@ import pc from "picocolors";
|
|
|
2463
2511
|
|
|
2464
2512
|
// src/showcase-bridge.ts
|
|
2465
2513
|
init_logger();
|
|
2466
|
-
import
|
|
2467
|
-
import
|
|
2514
|
+
import fs9 from "fs";
|
|
2515
|
+
import path9 from "path";
|
|
2468
2516
|
import os8 from "os";
|
|
2469
2517
|
var cachedManifest = null;
|
|
2470
2518
|
var cachedShowcaseRoot = null;
|
|
2471
2519
|
function findShowcaseRoot() {
|
|
2472
2520
|
const candidates = [
|
|
2473
2521
|
// Sibling in monorepo
|
|
2474
|
-
|
|
2475
|
-
|
|
2522
|
+
path9.join(os8.homedir(), "project-aman", "aman-showcase"),
|
|
2523
|
+
path9.join(process.cwd(), "..", "aman-showcase"),
|
|
2476
2524
|
// npm global install
|
|
2477
|
-
|
|
2525
|
+
path9.join(process.cwd(), "node_modules", "@aman_asmuei", "aman-showcase")
|
|
2478
2526
|
];
|
|
2479
2527
|
for (const candidate of candidates) {
|
|
2480
|
-
if (
|
|
2528
|
+
if (fs9.existsSync(path9.join(candidate, "src", "manifest.ts")) || fs9.existsSync(path9.join(candidate, "dist", "index.js"))) {
|
|
2481
2529
|
return candidate;
|
|
2482
2530
|
}
|
|
2483
2531
|
}
|
|
@@ -2507,10 +2555,10 @@ function loadShowcaseManifest() {
|
|
|
2507
2555
|
return cachedManifest;
|
|
2508
2556
|
}
|
|
2509
2557
|
cachedShowcaseRoot = root;
|
|
2510
|
-
const manifestSrc =
|
|
2511
|
-
if (
|
|
2558
|
+
const manifestSrc = path9.join(root, "src", "manifest.ts");
|
|
2559
|
+
if (fs9.existsSync(manifestSrc)) {
|
|
2512
2560
|
try {
|
|
2513
|
-
const content =
|
|
2561
|
+
const content = fs9.readFileSync(manifestSrc, "utf-8");
|
|
2514
2562
|
const parsed = parseManifestSource(content);
|
|
2515
2563
|
if (parsed.length > 0) {
|
|
2516
2564
|
cachedManifest = parsed;
|
|
@@ -2521,7 +2569,7 @@ function loadShowcaseManifest() {
|
|
|
2521
2569
|
}
|
|
2522
2570
|
}
|
|
2523
2571
|
try {
|
|
2524
|
-
const dirs =
|
|
2572
|
+
const dirs = fs9.readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".") && !["node_modules", "dist", "src", "bin", "docs"].includes(d.name)).filter((d) => fs9.existsSync(path9.join(root, d.name, "identity")));
|
|
2525
2573
|
cachedManifest = dirs.map((d) => ({
|
|
2526
2574
|
name: d.name,
|
|
2527
2575
|
title: d.name.charAt(0).toUpperCase() + d.name.slice(1),
|
|
@@ -2540,69 +2588,69 @@ function installShowcaseTemplate(name) {
|
|
|
2540
2588
|
if (!root) {
|
|
2541
2589
|
throw new Error("aman-showcase package not found. Install it or check the path.");
|
|
2542
2590
|
}
|
|
2543
|
-
const showcaseDir =
|
|
2544
|
-
if (!
|
|
2591
|
+
const showcaseDir = path9.join(root, name);
|
|
2592
|
+
if (!fs9.existsSync(showcaseDir) || !fs9.existsSync(path9.join(showcaseDir, "identity"))) {
|
|
2545
2593
|
throw new Error(`Showcase "${name}" not found in ${root}`);
|
|
2546
2594
|
}
|
|
2547
2595
|
const result = { installed: [], backed_up: [], env_example: "" };
|
|
2548
2596
|
const home2 = os8.homedir();
|
|
2549
2597
|
const copies = [
|
|
2550
2598
|
{
|
|
2551
|
-
src:
|
|
2552
|
-
dest:
|
|
2599
|
+
src: path9.join(showcaseDir, "identity", "core.md"),
|
|
2600
|
+
dest: path9.join(home2, ".acore", "core.md"),
|
|
2553
2601
|
label: "~/.acore/core.md (identity)"
|
|
2554
2602
|
},
|
|
2555
2603
|
{
|
|
2556
|
-
src:
|
|
2557
|
-
dest:
|
|
2604
|
+
src: path9.join(showcaseDir, "workflows", "flow.md"),
|
|
2605
|
+
dest: path9.join(home2, ".aflow", "flow.md"),
|
|
2558
2606
|
label: "~/.aflow/flow.md (workflows)"
|
|
2559
2607
|
},
|
|
2560
2608
|
{
|
|
2561
|
-
src:
|
|
2562
|
-
dest:
|
|
2609
|
+
src: path9.join(showcaseDir, "rules", "rules.md"),
|
|
2610
|
+
dest: path9.join(home2, ".arules", "rules.md"),
|
|
2563
2611
|
label: "~/.arules/rules.md (guardrails)"
|
|
2564
2612
|
}
|
|
2565
2613
|
];
|
|
2566
|
-
const skillsSrc =
|
|
2567
|
-
if (
|
|
2568
|
-
const skillFiles =
|
|
2614
|
+
const skillsSrc = path9.join(showcaseDir, "skills");
|
|
2615
|
+
if (fs9.existsSync(skillsSrc)) {
|
|
2616
|
+
const skillFiles = fs9.readdirSync(skillsSrc).filter((f) => f.endsWith(".md"));
|
|
2569
2617
|
if (skillFiles.length > 0) {
|
|
2570
2618
|
const skillParts = [];
|
|
2571
2619
|
for (const skillFile of skillFiles) {
|
|
2572
|
-
const content =
|
|
2620
|
+
const content = fs9.readFileSync(path9.join(skillsSrc, skillFile), "utf-8").trim();
|
|
2573
2621
|
if (content) skillParts.push(content);
|
|
2574
2622
|
}
|
|
2575
2623
|
if (skillParts.length > 0) {
|
|
2576
|
-
const skillsDest =
|
|
2624
|
+
const skillsDest = path9.join(home2, ".askill", "skills.md");
|
|
2577
2625
|
const consolidated = `# Skills
|
|
2578
2626
|
|
|
2579
2627
|
${skillParts.join("\n\n---\n\n")}
|
|
2580
2628
|
`;
|
|
2581
|
-
if (
|
|
2582
|
-
|
|
2629
|
+
if (fs9.existsSync(skillsDest)) {
|
|
2630
|
+
fs9.copyFileSync(skillsDest, `${skillsDest}.bak`);
|
|
2583
2631
|
result.backed_up.push("~/.askill/skills.md (skills)");
|
|
2584
2632
|
}
|
|
2585
|
-
|
|
2586
|
-
|
|
2633
|
+
fs9.mkdirSync(path9.dirname(skillsDest), { recursive: true });
|
|
2634
|
+
fs9.writeFileSync(skillsDest, consolidated, "utf-8");
|
|
2587
2635
|
result.installed.push(`~/.askill/skills.md (${skillFiles.length} skill${skillFiles.length > 1 ? "s" : ""} consolidated)`);
|
|
2588
2636
|
}
|
|
2589
2637
|
}
|
|
2590
2638
|
}
|
|
2591
2639
|
for (const { src, dest, label } of copies) {
|
|
2592
|
-
if (!
|
|
2593
|
-
if (
|
|
2640
|
+
if (!fs9.existsSync(src)) continue;
|
|
2641
|
+
if (fs9.existsSync(dest)) {
|
|
2594
2642
|
const backup = `${dest}.bak`;
|
|
2595
|
-
|
|
2643
|
+
fs9.copyFileSync(dest, backup);
|
|
2596
2644
|
result.backed_up.push(label);
|
|
2597
2645
|
}
|
|
2598
|
-
|
|
2599
|
-
|
|
2646
|
+
fs9.mkdirSync(path9.dirname(dest), { recursive: true });
|
|
2647
|
+
fs9.copyFileSync(src, dest);
|
|
2600
2648
|
result.installed.push(label);
|
|
2601
2649
|
}
|
|
2602
|
-
const envExample =
|
|
2603
|
-
if (
|
|
2604
|
-
const destEnv =
|
|
2605
|
-
|
|
2650
|
+
const envExample = path9.join(showcaseDir, "config", "telegram.env.example");
|
|
2651
|
+
if (fs9.existsSync(envExample)) {
|
|
2652
|
+
const destEnv = path9.join(process.cwd(), ".env.example");
|
|
2653
|
+
fs9.copyFileSync(envExample, destEnv);
|
|
2606
2654
|
result.env_example = destEnv;
|
|
2607
2655
|
}
|
|
2608
2656
|
log.debug("showcase", `Installed showcase: ${name} (${result.installed.length} files)`);
|
|
@@ -2862,31 +2910,31 @@ async function editProfile(current) {
|
|
|
2862
2910
|
}
|
|
2863
2911
|
|
|
2864
2912
|
// src/files.ts
|
|
2865
|
-
import
|
|
2866
|
-
import
|
|
2913
|
+
import fs10 from "fs";
|
|
2914
|
+
import path10 from "path";
|
|
2867
2915
|
import os9 from "os";
|
|
2868
2916
|
var MAX_READ_BYTES = 5e4;
|
|
2869
|
-
var HOME =
|
|
2870
|
-
var TMPDIR =
|
|
2871
|
-
var CWD =
|
|
2917
|
+
var HOME = fs10.realpathSync(os9.homedir());
|
|
2918
|
+
var TMPDIR = fs10.realpathSync(os9.tmpdir());
|
|
2919
|
+
var CWD = fs10.realpathSync(process.cwd());
|
|
2872
2920
|
function realOrBest(p5) {
|
|
2873
|
-
const parts = p5.split(
|
|
2921
|
+
const parts = p5.split(path10.sep);
|
|
2874
2922
|
for (let i = parts.length; i > 0; i--) {
|
|
2875
|
-
const candidate = parts.slice(0, i).join(
|
|
2923
|
+
const candidate = parts.slice(0, i).join(path10.sep) || path10.sep;
|
|
2876
2924
|
try {
|
|
2877
|
-
const real =
|
|
2878
|
-
const remainder = parts.slice(i).join(
|
|
2879
|
-
return remainder ? `${real}${
|
|
2925
|
+
const real = fs10.realpathSync(candidate);
|
|
2926
|
+
const remainder = parts.slice(i).join(path10.sep);
|
|
2927
|
+
return remainder ? `${real}${path10.sep}${remainder}` : real;
|
|
2880
2928
|
} catch {
|
|
2881
2929
|
}
|
|
2882
2930
|
}
|
|
2883
2931
|
return p5;
|
|
2884
2932
|
}
|
|
2885
2933
|
function isUnderDir(real, dir) {
|
|
2886
|
-
return real === dir || real.startsWith(dir +
|
|
2934
|
+
return real === dir || real.startsWith(dir + path10.sep);
|
|
2887
2935
|
}
|
|
2888
2936
|
function assertSafePath(filePath) {
|
|
2889
|
-
const resolved =
|
|
2937
|
+
const resolved = path10.resolve(filePath);
|
|
2890
2938
|
const real = realOrBest(resolved);
|
|
2891
2939
|
if (!isUnderDir(real, HOME) && !isUnderDir(real, CWD) && !isUnderDir(real, TMPDIR)) {
|
|
2892
2940
|
throw new Error(`Path is outside allowed directories (home or cwd): ${real}`);
|
|
@@ -2895,20 +2943,20 @@ function assertSafePath(filePath) {
|
|
|
2895
2943
|
}
|
|
2896
2944
|
async function readFile(filePath) {
|
|
2897
2945
|
const resolved = assertSafePath(filePath);
|
|
2898
|
-
if (!
|
|
2946
|
+
if (!fs10.existsSync(resolved)) {
|
|
2899
2947
|
throw new Error(`File not found: ${resolved}`);
|
|
2900
2948
|
}
|
|
2901
|
-
const stat =
|
|
2949
|
+
const stat = fs10.statSync(resolved);
|
|
2902
2950
|
if (stat.isDirectory()) {
|
|
2903
2951
|
throw new Error(`Path is a directory, not a file: ${resolved}. Use /file list instead.`);
|
|
2904
2952
|
}
|
|
2905
2953
|
const size = stat.size;
|
|
2906
2954
|
const buf = Buffer.alloc(Math.min(size, MAX_READ_BYTES));
|
|
2907
|
-
const fd =
|
|
2955
|
+
const fd = fs10.openSync(resolved, "r");
|
|
2908
2956
|
try {
|
|
2909
|
-
|
|
2957
|
+
fs10.readSync(fd, buf, 0, buf.length, 0);
|
|
2910
2958
|
} finally {
|
|
2911
|
-
|
|
2959
|
+
fs10.closeSync(fd);
|
|
2912
2960
|
}
|
|
2913
2961
|
return {
|
|
2914
2962
|
path: resolved,
|
|
@@ -2920,23 +2968,23 @@ async function readFile(filePath) {
|
|
|
2920
2968
|
}
|
|
2921
2969
|
async function listFiles(dirPath, opts = {}) {
|
|
2922
2970
|
const resolved = assertSafePath(dirPath);
|
|
2923
|
-
if (!
|
|
2971
|
+
if (!fs10.existsSync(resolved)) {
|
|
2924
2972
|
throw new Error(`Directory not found: ${resolved}`);
|
|
2925
2973
|
}
|
|
2926
|
-
const stat =
|
|
2974
|
+
const stat = fs10.statSync(resolved);
|
|
2927
2975
|
if (!stat.isDirectory()) {
|
|
2928
2976
|
throw new Error(`Path is a file, not a directory: ${resolved}. Use /file read instead.`);
|
|
2929
2977
|
}
|
|
2930
2978
|
const entries = [];
|
|
2931
2979
|
function walk(dir, prefix) {
|
|
2932
|
-
const items =
|
|
2980
|
+
const items = fs10.readdirSync(dir, { withFileTypes: true });
|
|
2933
2981
|
for (const item of items) {
|
|
2934
2982
|
const rel = prefix ? `${prefix}/${item.name}` : item.name;
|
|
2935
2983
|
if (item.isDirectory()) {
|
|
2936
2984
|
entries.push({ name: rel, type: "dir", size: 0 });
|
|
2937
|
-
if (opts.recursive) walk(
|
|
2985
|
+
if (opts.recursive) walk(path10.join(dir, item.name), rel);
|
|
2938
2986
|
} else {
|
|
2939
|
-
const s =
|
|
2987
|
+
const s = fs10.statSync(path10.join(dir, item.name));
|
|
2940
2988
|
entries.push({ name: rel, type: "file", size: s.size });
|
|
2941
2989
|
}
|
|
2942
2990
|
}
|
|
@@ -2953,8 +3001,8 @@ init_logger();
|
|
|
2953
3001
|
init_logger();
|
|
2954
3002
|
import pc2 from "picocolors";
|
|
2955
3003
|
import * as p2 from "@clack/prompts";
|
|
2956
|
-
import
|
|
2957
|
-
import
|
|
3004
|
+
import fs15 from "fs";
|
|
3005
|
+
import path15 from "path";
|
|
2958
3006
|
import os13 from "os";
|
|
2959
3007
|
|
|
2960
3008
|
// src/personality.ts
|
|
@@ -3149,13 +3197,13 @@ async function syncPersonalityToCore(state, mcpManager, modelMetrics) {
|
|
|
3149
3197
|
}
|
|
3150
3198
|
|
|
3151
3199
|
// src/postmortem.ts
|
|
3152
|
-
import
|
|
3153
|
-
import
|
|
3200
|
+
import fs12 from "fs/promises";
|
|
3201
|
+
import path12 from "path";
|
|
3154
3202
|
import os11 from "os";
|
|
3155
3203
|
|
|
3156
3204
|
// src/observation.ts
|
|
3157
|
-
import
|
|
3158
|
-
import
|
|
3205
|
+
import fs11 from "fs/promises";
|
|
3206
|
+
import path11 from "path";
|
|
3159
3207
|
import os10 from "os";
|
|
3160
3208
|
var STAT_MAP = {
|
|
3161
3209
|
tool_call: "toolCalls",
|
|
@@ -3166,7 +3214,7 @@ var STAT_MAP = {
|
|
|
3166
3214
|
file_change: "fileChanges"
|
|
3167
3215
|
};
|
|
3168
3216
|
function defaultObservationsDir() {
|
|
3169
|
-
return
|
|
3217
|
+
return path11.join(os10.homedir(), ".acore", "observations");
|
|
3170
3218
|
}
|
|
3171
3219
|
function createObservationSession(sessionId) {
|
|
3172
3220
|
return {
|
|
@@ -3202,17 +3250,17 @@ function resumeObservation(session) {
|
|
|
3202
3250
|
async function flushEvents(session, dir) {
|
|
3203
3251
|
if (session.events.length === 0) return;
|
|
3204
3252
|
const obsDir = dir ?? defaultObservationsDir();
|
|
3205
|
-
await
|
|
3206
|
-
const filePath =
|
|
3253
|
+
await fs11.mkdir(obsDir, { recursive: true });
|
|
3254
|
+
const filePath = path11.join(obsDir, `${session.sessionId}.jsonl`);
|
|
3207
3255
|
const lines = session.events.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
3208
|
-
await
|
|
3256
|
+
await fs11.appendFile(filePath, lines, "utf-8");
|
|
3209
3257
|
session.events.length = 0;
|
|
3210
3258
|
}
|
|
3211
3259
|
async function readObservationEvents(sessionId, dir) {
|
|
3212
3260
|
const obsDir = dir ?? defaultObservationsDir();
|
|
3213
|
-
const filePath =
|
|
3261
|
+
const filePath = path11.join(obsDir, `${sessionId}.jsonl`);
|
|
3214
3262
|
try {
|
|
3215
|
-
const content = await
|
|
3263
|
+
const content = await fs11.readFile(filePath, "utf-8");
|
|
3216
3264
|
return content.trim().split("\n").filter((line) => line.length > 0).map((line) => JSON.parse(line));
|
|
3217
3265
|
} catch {
|
|
3218
3266
|
return [];
|
|
@@ -3235,14 +3283,14 @@ function getSessionStats(session) {
|
|
|
3235
3283
|
async function cleanupOldObservations(dir, maxAgeDays = 30) {
|
|
3236
3284
|
const obsDir = dir ?? defaultObservationsDir();
|
|
3237
3285
|
try {
|
|
3238
|
-
const files = await
|
|
3286
|
+
const files = await fs11.readdir(obsDir);
|
|
3239
3287
|
const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
|
|
3240
3288
|
for (const file of files) {
|
|
3241
3289
|
if (!file.endsWith(".jsonl")) continue;
|
|
3242
|
-
const filePath =
|
|
3243
|
-
const stat = await
|
|
3290
|
+
const filePath = path11.join(obsDir, file);
|
|
3291
|
+
const stat = await fs11.stat(filePath);
|
|
3244
3292
|
if (stat.mtimeMs < cutoff) {
|
|
3245
|
-
await
|
|
3293
|
+
await fs11.unlink(filePath);
|
|
3246
3294
|
}
|
|
3247
3295
|
}
|
|
3248
3296
|
} catch {
|
|
@@ -3269,10 +3317,10 @@ function detectTopicShift(recentMessages, previousMessages) {
|
|
|
3269
3317
|
// src/postmortem.ts
|
|
3270
3318
|
init_logger();
|
|
3271
3319
|
function defaultPostmortemsDir() {
|
|
3272
|
-
return
|
|
3320
|
+
return path12.join(os11.homedir(), ".acore", "postmortems");
|
|
3273
3321
|
}
|
|
3274
3322
|
function defaultObservationsDir2() {
|
|
3275
|
-
return
|
|
3323
|
+
return path12.join(os11.homedir(), ".acore", "observations");
|
|
3276
3324
|
}
|
|
3277
3325
|
function shouldAutoPostmortem(session, messages) {
|
|
3278
3326
|
if (messages.length < 6) return false;
|
|
@@ -3491,15 +3539,15 @@ function formatPostmortemMarkdown(report) {
|
|
|
3491
3539
|
}
|
|
3492
3540
|
async function savePostmortem(report, dir) {
|
|
3493
3541
|
const pmDir = dir ?? defaultPostmortemsDir();
|
|
3494
|
-
await
|
|
3542
|
+
await fs12.mkdir(pmDir, { recursive: true });
|
|
3495
3543
|
const shortId = report.sessionId.slice(0, 4);
|
|
3496
3544
|
const fileName = `${report.date}-${shortId}.md`;
|
|
3497
|
-
const filePath =
|
|
3545
|
+
const filePath = path12.join(pmDir, fileName);
|
|
3498
3546
|
const markdown = formatPostmortemMarkdown(report);
|
|
3499
|
-
await
|
|
3547
|
+
await fs12.writeFile(filePath, markdown, "utf-8");
|
|
3500
3548
|
const jsonPath = filePath.replace(/\.md$/, ".json");
|
|
3501
3549
|
try {
|
|
3502
|
-
await
|
|
3550
|
+
await fs12.writeFile(jsonPath, JSON.stringify(report, null, 2), "utf-8");
|
|
3503
3551
|
} catch (err) {
|
|
3504
3552
|
log.debug("postmortem", "JSON sidecar write failed", err);
|
|
3505
3553
|
}
|
|
@@ -3508,7 +3556,7 @@ async function savePostmortem(report, dir) {
|
|
|
3508
3556
|
async function listPostmortems(dir) {
|
|
3509
3557
|
const pmDir = dir ?? defaultPostmortemsDir();
|
|
3510
3558
|
try {
|
|
3511
|
-
const files = await
|
|
3559
|
+
const files = await fs12.readdir(pmDir);
|
|
3512
3560
|
return files.filter((f) => f.endsWith(".md")).sort().reverse();
|
|
3513
3561
|
} catch {
|
|
3514
3562
|
return [];
|
|
@@ -3518,7 +3566,7 @@ async function readPostmortem(name, dir) {
|
|
|
3518
3566
|
const pmDir = dir ?? defaultPostmortemsDir();
|
|
3519
3567
|
const fileName = name.endsWith(".md") ? name : `${name}.md`;
|
|
3520
3568
|
try {
|
|
3521
|
-
return await
|
|
3569
|
+
return await fs12.readFile(path12.join(pmDir, fileName), "utf-8");
|
|
3522
3570
|
} catch {
|
|
3523
3571
|
return null;
|
|
3524
3572
|
}
|
|
@@ -3565,8 +3613,8 @@ ${contents.join("\n\n---\n\n")}`
|
|
|
3565
3613
|
|
|
3566
3614
|
// src/crystallization.ts
|
|
3567
3615
|
init_logger();
|
|
3568
|
-
import
|
|
3569
|
-
import
|
|
3616
|
+
import fs13 from "fs/promises";
|
|
3617
|
+
import path13 from "path";
|
|
3570
3618
|
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
3571
3619
|
"the",
|
|
3572
3620
|
"and",
|
|
@@ -3731,10 +3779,10 @@ function findCollision(name, triggers, existing) {
|
|
|
3731
3779
|
}
|
|
3732
3780
|
async function writeSkillToFile(candidate, skillsMdPath, postmortemFilename) {
|
|
3733
3781
|
try {
|
|
3734
|
-
await
|
|
3782
|
+
await fs13.mkdir(path13.dirname(skillsMdPath), { recursive: true });
|
|
3735
3783
|
let existingContent = "";
|
|
3736
3784
|
try {
|
|
3737
|
-
existingContent = await
|
|
3785
|
+
existingContent = await fs13.readFile(skillsMdPath, "utf-8");
|
|
3738
3786
|
} catch {
|
|
3739
3787
|
existingContent = "# Skills\n\n";
|
|
3740
3788
|
}
|
|
@@ -3755,7 +3803,7 @@ async function writeSkillToFile(candidate, skillsMdPath, postmortemFilename) {
|
|
|
3755
3803
|
}
|
|
3756
3804
|
const skillMarkdown = formatSkillMarkdown(candidate, postmortemFilename);
|
|
3757
3805
|
const separator = existingContent.endsWith("\n\n") ? "" : existingContent.endsWith("\n") ? "\n" : "\n\n";
|
|
3758
|
-
await
|
|
3806
|
+
await fs13.writeFile(
|
|
3759
3807
|
skillsMdPath,
|
|
3760
3808
|
existingContent + separator + skillMarkdown,
|
|
3761
3809
|
"utf-8"
|
|
@@ -3777,7 +3825,7 @@ async function writeSkillToFile(candidate, skillsMdPath, postmortemFilename) {
|
|
|
3777
3825
|
}
|
|
3778
3826
|
async function mergeSkillInFile(candidate, existingName, skillsMdPath, postmortemFilename) {
|
|
3779
3827
|
try {
|
|
3780
|
-
const content = await
|
|
3828
|
+
const content = await fs13.readFile(skillsMdPath, "utf-8");
|
|
3781
3829
|
const lines = content.split("\n");
|
|
3782
3830
|
const heading = toTitleCase(existingName);
|
|
3783
3831
|
let startIdx = -1;
|
|
@@ -3818,7 +3866,7 @@ async function mergeSkillInFile(candidate, existingName, skillsMdPath, postmorte
|
|
|
3818
3866
|
const before = lines.slice(0, startIdx);
|
|
3819
3867
|
const after = lines.slice(endIdx);
|
|
3820
3868
|
const merged = [...before, ...oldBlock, "", newSkillMarkdown, ...after].join("\n");
|
|
3821
|
-
await
|
|
3869
|
+
await fs13.writeFile(skillsMdPath, merged, "utf-8");
|
|
3822
3870
|
return {
|
|
3823
3871
|
written: true,
|
|
3824
3872
|
filePath: skillsMdPath,
|
|
@@ -3837,27 +3885,27 @@ async function mergeSkillInFile(candidate, existingName, skillsMdPath, postmorte
|
|
|
3837
3885
|
}
|
|
3838
3886
|
async function appendCrystallizationLog(entry, logPath) {
|
|
3839
3887
|
try {
|
|
3840
|
-
await
|
|
3888
|
+
await fs13.mkdir(path13.dirname(logPath), { recursive: true });
|
|
3841
3889
|
let existing = [];
|
|
3842
3890
|
try {
|
|
3843
|
-
const content = await
|
|
3891
|
+
const content = await fs13.readFile(logPath, "utf-8");
|
|
3844
3892
|
existing = JSON.parse(content);
|
|
3845
3893
|
if (!Array.isArray(existing)) existing = [];
|
|
3846
3894
|
} catch {
|
|
3847
3895
|
existing = [];
|
|
3848
3896
|
}
|
|
3849
3897
|
existing.push(entry);
|
|
3850
|
-
await
|
|
3898
|
+
await fs13.writeFile(logPath, JSON.stringify(existing, null, 2), "utf-8");
|
|
3851
3899
|
} catch (err) {
|
|
3852
3900
|
log.debug("crystallization", "appendCrystallizationLog failed", err);
|
|
3853
3901
|
}
|
|
3854
3902
|
}
|
|
3855
3903
|
async function appendRejection(candidate, postmortemFilename, rejectionsPath) {
|
|
3856
3904
|
try {
|
|
3857
|
-
await
|
|
3905
|
+
await fs13.mkdir(path13.dirname(rejectionsPath), { recursive: true });
|
|
3858
3906
|
let existing = [];
|
|
3859
3907
|
try {
|
|
3860
|
-
const content = await
|
|
3908
|
+
const content = await fs13.readFile(rejectionsPath, "utf-8");
|
|
3861
3909
|
existing = JSON.parse(content);
|
|
3862
3910
|
if (!Array.isArray(existing)) existing = [];
|
|
3863
3911
|
} catch {
|
|
@@ -3872,14 +3920,14 @@ async function appendRejection(candidate, postmortemFilename, rejectionsPath) {
|
|
|
3872
3920
|
while (existing.length > MAX_REJECTIONS) {
|
|
3873
3921
|
existing.shift();
|
|
3874
3922
|
}
|
|
3875
|
-
await
|
|
3923
|
+
await fs13.writeFile(rejectionsPath, JSON.stringify(existing, null, 2), "utf-8");
|
|
3876
3924
|
} catch (err) {
|
|
3877
3925
|
log.debug("crystallization", "appendRejection failed", err);
|
|
3878
3926
|
}
|
|
3879
3927
|
}
|
|
3880
3928
|
async function loadRejectedNames(rejectionsPath) {
|
|
3881
3929
|
try {
|
|
3882
|
-
const content = await
|
|
3930
|
+
const content = await fs13.readFile(rejectionsPath, "utf-8");
|
|
3883
3931
|
const entries = JSON.parse(content);
|
|
3884
3932
|
if (!Array.isArray(entries)) return [];
|
|
3885
3933
|
return [...new Set(entries.map((e) => e.name))];
|
|
@@ -3889,7 +3937,7 @@ async function loadRejectedNames(rejectionsPath) {
|
|
|
3889
3937
|
}
|
|
3890
3938
|
async function loadSuggestionCounts(suggestionsPath) {
|
|
3891
3939
|
try {
|
|
3892
|
-
const content = await
|
|
3940
|
+
const content = await fs13.readFile(suggestionsPath, "utf-8");
|
|
3893
3941
|
const parsed = JSON.parse(content);
|
|
3894
3942
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
3895
3943
|
return parsed;
|
|
@@ -3899,10 +3947,10 @@ async function loadSuggestionCounts(suggestionsPath) {
|
|
|
3899
3947
|
}
|
|
3900
3948
|
async function incrementSuggestionCount(name, suggestionsPath) {
|
|
3901
3949
|
try {
|
|
3902
|
-
await
|
|
3950
|
+
await fs13.mkdir(path13.dirname(suggestionsPath), { recursive: true });
|
|
3903
3951
|
const counts = await loadSuggestionCounts(suggestionsPath);
|
|
3904
3952
|
counts[name] = (counts[name] || 0) + 1;
|
|
3905
|
-
await
|
|
3953
|
+
await fs13.writeFile(suggestionsPath, JSON.stringify(counts, null, 2), "utf-8");
|
|
3906
3954
|
return counts[name];
|
|
3907
3955
|
} catch (err) {
|
|
3908
3956
|
log.debug("crystallization", "incrementSuggestionCount failed", err);
|
|
@@ -4213,10 +4261,10 @@ async function onSessionEnd(ctx, messages, sessionId, observationSession) {
|
|
|
4213
4261
|
}
|
|
4214
4262
|
console.log(pc2.dim(` Saved ${textMessages.length} messages (session: ${sessionId})`));
|
|
4215
4263
|
}
|
|
4216
|
-
const projectContextPath =
|
|
4217
|
-
if (
|
|
4264
|
+
const projectContextPath = path15.join(process.cwd(), ".acore", "context.md");
|
|
4265
|
+
if (fs15.existsSync(projectContextPath) && messages.length > 2) {
|
|
4218
4266
|
try {
|
|
4219
|
-
let contextContent =
|
|
4267
|
+
let contextContent = fs15.readFileSync(projectContextPath, "utf-8");
|
|
4220
4268
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
4221
4269
|
let lastUserMsg = "";
|
|
4222
4270
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -4234,7 +4282,7 @@ async function onSessionEnd(ctx, messages, sessionId, observationSession) {
|
|
|
4234
4282
|
- Recent decisions: [see memory]
|
|
4235
4283
|
- Temp notes: [cleared]`;
|
|
4236
4284
|
contextContent = contextContent.replace(sessionPattern, newSession);
|
|
4237
|
-
|
|
4285
|
+
fs15.writeFileSync(projectContextPath, contextContent, "utf-8");
|
|
4238
4286
|
log.debug("hooks", `Updated project context: ${projectContextPath}`);
|
|
4239
4287
|
}
|
|
4240
4288
|
} catch (err) {
|
|
@@ -4338,7 +4386,7 @@ async function onSessionEnd(ctx, messages, sessionId, observationSession) {
|
|
|
4338
4386
|
try {
|
|
4339
4387
|
const client = ctx.llmClient;
|
|
4340
4388
|
if (client) {
|
|
4341
|
-
const rejectionsPath =
|
|
4389
|
+
const rejectionsPath = path15.join(
|
|
4342
4390
|
os13.homedir(),
|
|
4343
4391
|
".aman-agent",
|
|
4344
4392
|
"crystallization-rejections.json"
|
|
@@ -4368,18 +4416,18 @@ async function onSessionEnd(ctx, messages, sessionId, observationSession) {
|
|
|
4368
4416
|
}
|
|
4369
4417
|
}
|
|
4370
4418
|
if (report.crystallizationCandidates && report.crystallizationCandidates.length > 0) {
|
|
4371
|
-
const skillsMdPath =
|
|
4372
|
-
const logPath =
|
|
4419
|
+
const skillsMdPath = path15.join(os13.homedir(), ".askill", "skills.md");
|
|
4420
|
+
const logPath = path15.join(
|
|
4373
4421
|
os13.homedir(),
|
|
4374
4422
|
".aman-agent",
|
|
4375
4423
|
"crystallization-log.json"
|
|
4376
4424
|
);
|
|
4377
|
-
const rejectionsPath2 =
|
|
4425
|
+
const rejectionsPath2 = path15.join(
|
|
4378
4426
|
os13.homedir(),
|
|
4379
4427
|
".aman-agent",
|
|
4380
4428
|
"crystallization-rejections.json"
|
|
4381
4429
|
);
|
|
4382
|
-
const suggestionsPath =
|
|
4430
|
+
const suggestionsPath = path15.join(
|
|
4383
4431
|
os13.homedir(),
|
|
4384
4432
|
".aman-agent",
|
|
4385
4433
|
"crystallization-suggestions.json"
|
|
@@ -4658,43 +4706,43 @@ import { StreamableHTTPClientTransport as StreamableHTTPClientTransport2 } from
|
|
|
4658
4706
|
import { Client as Client3 } from "@modelcontextprotocol/sdk/client/index.js";
|
|
4659
4707
|
|
|
4660
4708
|
// src/teams.ts
|
|
4661
|
-
import
|
|
4662
|
-
import
|
|
4709
|
+
import fs17 from "fs";
|
|
4710
|
+
import path17 from "path";
|
|
4663
4711
|
import os15 from "os";
|
|
4664
4712
|
import pc4 from "picocolors";
|
|
4665
4713
|
function getTeamsDir() {
|
|
4666
|
-
return
|
|
4714
|
+
return path17.join(os15.homedir(), ".acore", "teams");
|
|
4667
4715
|
}
|
|
4668
4716
|
function ensureTeamsDir() {
|
|
4669
4717
|
const dir = getTeamsDir();
|
|
4670
|
-
if (!
|
|
4718
|
+
if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
|
|
4671
4719
|
return dir;
|
|
4672
4720
|
}
|
|
4673
4721
|
function teamPath(name) {
|
|
4674
4722
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
4675
|
-
return
|
|
4723
|
+
return path17.join(ensureTeamsDir(), `${slug}.json`);
|
|
4676
4724
|
}
|
|
4677
4725
|
function createTeam(team) {
|
|
4678
4726
|
const fp = teamPath(team.name);
|
|
4679
|
-
|
|
4727
|
+
fs17.writeFileSync(fp, JSON.stringify(team, null, 2), "utf-8");
|
|
4680
4728
|
}
|
|
4681
4729
|
function loadTeam(name) {
|
|
4682
4730
|
const fp = teamPath(name);
|
|
4683
|
-
if (!
|
|
4731
|
+
if (!fs17.existsSync(fp)) return null;
|
|
4684
4732
|
try {
|
|
4685
|
-
return JSON.parse(
|
|
4733
|
+
return JSON.parse(fs17.readFileSync(fp, "utf-8"));
|
|
4686
4734
|
} catch {
|
|
4687
4735
|
return null;
|
|
4688
4736
|
}
|
|
4689
4737
|
}
|
|
4690
4738
|
function listTeams() {
|
|
4691
4739
|
const dir = getTeamsDir();
|
|
4692
|
-
if (!
|
|
4740
|
+
if (!fs17.existsSync(dir)) return [];
|
|
4693
4741
|
const teams = [];
|
|
4694
|
-
for (const file of
|
|
4742
|
+
for (const file of fs17.readdirSync(dir)) {
|
|
4695
4743
|
if (!file.endsWith(".json")) continue;
|
|
4696
4744
|
try {
|
|
4697
|
-
const content =
|
|
4745
|
+
const content = fs17.readFileSync(path17.join(dir, file), "utf-8");
|
|
4698
4746
|
teams.push(JSON.parse(content));
|
|
4699
4747
|
} catch {
|
|
4700
4748
|
}
|
|
@@ -4703,8 +4751,8 @@ function listTeams() {
|
|
|
4703
4751
|
}
|
|
4704
4752
|
function deleteTeam(name) {
|
|
4705
4753
|
const fp = teamPath(name);
|
|
4706
|
-
if (!
|
|
4707
|
-
|
|
4754
|
+
if (!fs17.existsSync(fp)) return false;
|
|
4755
|
+
fs17.unlinkSync(fp);
|
|
4708
4756
|
return true;
|
|
4709
4757
|
}
|
|
4710
4758
|
async function runTeam(team, task, client, mcpManager, tools) {
|
|
@@ -4931,23 +4979,23 @@ var BUILT_IN_TEAMS = [
|
|
|
4931
4979
|
|
|
4932
4980
|
// src/plans.ts
|
|
4933
4981
|
init_logger();
|
|
4934
|
-
import
|
|
4935
|
-
import
|
|
4982
|
+
import fs18 from "fs";
|
|
4983
|
+
import path18 from "path";
|
|
4936
4984
|
import os16 from "os";
|
|
4937
4985
|
function getPlansDir() {
|
|
4938
|
-
const localDir =
|
|
4939
|
-
const localAcore =
|
|
4940
|
-
if (
|
|
4941
|
-
return
|
|
4986
|
+
const localDir = path18.join(process.cwd(), ".acore", "plans");
|
|
4987
|
+
const localAcore = path18.join(process.cwd(), ".acore");
|
|
4988
|
+
if (fs18.existsSync(localAcore)) return localDir;
|
|
4989
|
+
return path18.join(os16.homedir(), ".acore", "plans");
|
|
4942
4990
|
}
|
|
4943
4991
|
function ensurePlansDir() {
|
|
4944
4992
|
const dir = getPlansDir();
|
|
4945
|
-
if (!
|
|
4993
|
+
if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
|
|
4946
4994
|
return dir;
|
|
4947
4995
|
}
|
|
4948
4996
|
function planPath(name) {
|
|
4949
4997
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
4950
|
-
return
|
|
4998
|
+
return path18.join(ensurePlansDir(), `${slug}.md`);
|
|
4951
4999
|
}
|
|
4952
5000
|
function serializePlan(plan) {
|
|
4953
5001
|
const lines = [];
|
|
@@ -4973,7 +5021,7 @@ function parsePlan(content, filePath) {
|
|
|
4973
5021
|
const createdMatch = content.match(/\*\*Created:\*\*\s*(.+)/);
|
|
4974
5022
|
const updatedMatch = content.match(/\*\*Updated:\*\*\s*(.+)/);
|
|
4975
5023
|
const activeMatch = content.match(/\*\*Active:\*\*\s*(.+)/);
|
|
4976
|
-
const name = nameMatch?.[1]?.trim() ||
|
|
5024
|
+
const name = nameMatch?.[1]?.trim() || path18.basename(filePath, ".md");
|
|
4977
5025
|
const goal = goalMatch?.[1]?.trim() || "";
|
|
4978
5026
|
const createdAt = createdMatch?.[1]?.trim() || "";
|
|
4979
5027
|
const updatedAt = updatedMatch?.[1]?.trim() || "";
|
|
@@ -5015,22 +5063,22 @@ function createPlan(name, goal, steps) {
|
|
|
5015
5063
|
}
|
|
5016
5064
|
function savePlan(plan) {
|
|
5017
5065
|
const fp = planPath(plan.name);
|
|
5018
|
-
|
|
5066
|
+
fs18.writeFileSync(fp, serializePlan(plan), "utf-8");
|
|
5019
5067
|
}
|
|
5020
5068
|
function loadPlan(name) {
|
|
5021
5069
|
const fp = planPath(name);
|
|
5022
|
-
if (!
|
|
5023
|
-
const content =
|
|
5070
|
+
if (!fs18.existsSync(fp)) return null;
|
|
5071
|
+
const content = fs18.readFileSync(fp, "utf-8");
|
|
5024
5072
|
return parsePlan(content, fp);
|
|
5025
5073
|
}
|
|
5026
5074
|
function listPlans() {
|
|
5027
5075
|
const dir = getPlansDir();
|
|
5028
|
-
if (!
|
|
5076
|
+
if (!fs18.existsSync(dir)) return [];
|
|
5029
5077
|
const plans = [];
|
|
5030
|
-
for (const file of
|
|
5078
|
+
for (const file of fs18.readdirSync(dir)) {
|
|
5031
5079
|
if (!file.endsWith(".md")) continue;
|
|
5032
|
-
const fp =
|
|
5033
|
-
const content =
|
|
5080
|
+
const fp = path18.join(dir, file);
|
|
5081
|
+
const content = fs18.readFileSync(fp, "utf-8");
|
|
5034
5082
|
const plan = parsePlan(content, fp);
|
|
5035
5083
|
if (plan) plans.push(plan);
|
|
5036
5084
|
}
|
|
@@ -5129,8 +5177,8 @@ init_user_model();
|
|
|
5129
5177
|
|
|
5130
5178
|
// src/background.ts
|
|
5131
5179
|
init_logger();
|
|
5132
|
-
import
|
|
5133
|
-
import
|
|
5180
|
+
import fs19 from "fs";
|
|
5181
|
+
import path19 from "path";
|
|
5134
5182
|
import os17 from "os";
|
|
5135
5183
|
import pc5 from "picocolors";
|
|
5136
5184
|
var BACKGROUND_ELIGIBLE = /* @__PURE__ */ new Set([
|
|
@@ -5170,13 +5218,13 @@ var NEVER_BACKGROUND = /* @__PURE__ */ new Set([
|
|
|
5170
5218
|
"file_list",
|
|
5171
5219
|
"avatar_prompt"
|
|
5172
5220
|
]);
|
|
5173
|
-
var TASK_LOG_DIR =
|
|
5174
|
-
var TASK_LOG_FILE =
|
|
5221
|
+
var TASK_LOG_DIR = path19.join(os17.homedir(), ".aman-agent");
|
|
5222
|
+
var TASK_LOG_FILE = path19.join(TASK_LOG_DIR, "bg-tasks.json");
|
|
5175
5223
|
var MAX_LOG_ENTRIES = 50;
|
|
5176
5224
|
function loadTaskLog() {
|
|
5177
5225
|
try {
|
|
5178
|
-
if (!
|
|
5179
|
-
const raw =
|
|
5226
|
+
if (!fs19.existsSync(TASK_LOG_FILE)) return [];
|
|
5227
|
+
const raw = fs19.readFileSync(TASK_LOG_FILE, "utf-8");
|
|
5180
5228
|
return JSON.parse(raw);
|
|
5181
5229
|
} catch {
|
|
5182
5230
|
return [];
|
|
@@ -5184,9 +5232,9 @@ function loadTaskLog() {
|
|
|
5184
5232
|
}
|
|
5185
5233
|
function saveTaskLog(entries) {
|
|
5186
5234
|
try {
|
|
5187
|
-
if (!
|
|
5235
|
+
if (!fs19.existsSync(TASK_LOG_DIR)) fs19.mkdirSync(TASK_LOG_DIR, { recursive: true });
|
|
5188
5236
|
const trimmed = entries.slice(-MAX_LOG_ENTRIES);
|
|
5189
|
-
|
|
5237
|
+
fs19.writeFileSync(TASK_LOG_FILE, JSON.stringify(trimmed, null, 2));
|
|
5190
5238
|
} catch (err) {
|
|
5191
5239
|
log.debug("background", "Failed to save task log", err);
|
|
5192
5240
|
}
|
|
@@ -5335,10 +5383,10 @@ import {
|
|
|
5335
5383
|
} from "@aman_asmuei/arules-core";
|
|
5336
5384
|
var AGENT_SCOPE = process.env.AMAN_AGENT_SCOPE ?? "dev:agent";
|
|
5337
5385
|
function readEcosystemFile(filePath, label) {
|
|
5338
|
-
if (!
|
|
5386
|
+
if (!fs20.existsSync(filePath)) {
|
|
5339
5387
|
return pc6.dim(`No ${label} file found at ${filePath}`);
|
|
5340
5388
|
}
|
|
5341
|
-
return
|
|
5389
|
+
return fs20.readFileSync(filePath, "utf-8").trim();
|
|
5342
5390
|
}
|
|
5343
5391
|
function parseCommand(input) {
|
|
5344
5392
|
const trimmed = input.trim();
|
|
@@ -5423,8 +5471,8 @@ async function handleIdentityCommand(action, args, _ctx) {
|
|
|
5423
5471
|
}
|
|
5424
5472
|
if (args.includes("--reset")) {
|
|
5425
5473
|
const modelPath = defaultModelPath();
|
|
5426
|
-
if (
|
|
5427
|
-
|
|
5474
|
+
if (fs20.existsSync(modelPath)) {
|
|
5475
|
+
fs20.unlinkSync(modelPath);
|
|
5428
5476
|
return { handled: true, output: pc6.green("User model reset. Starting fresh.") };
|
|
5429
5477
|
}
|
|
5430
5478
|
return { handled: true, output: pc6.dim("No user model to reset.") };
|
|
@@ -5670,7 +5718,7 @@ ${result.violations.map((v) => ` - ${v}`).join("\n")}`)
|
|
|
5670
5718
|
async function handleWorkflowsCommand(action, args, ctx) {
|
|
5671
5719
|
const home2 = os18.homedir();
|
|
5672
5720
|
if (!action) {
|
|
5673
|
-
const content = readEcosystemFile(
|
|
5721
|
+
const content = readEcosystemFile(path20.join(home2, ".aflow", "flow.md"), "workflows (aflow)");
|
|
5674
5722
|
return { handled: true, output: content };
|
|
5675
5723
|
}
|
|
5676
5724
|
if (action === "add") {
|
|
@@ -5692,7 +5740,7 @@ async function handleWorkflowsCommand(action, args, ctx) {
|
|
|
5692
5740
|
return { handled: true, output: pc6.yellow("Usage: /workflows get <name>") };
|
|
5693
5741
|
}
|
|
5694
5742
|
const name = args.join(" ").toLowerCase();
|
|
5695
|
-
const raw = readEcosystemFile(
|
|
5743
|
+
const raw = readEcosystemFile(path20.join(home2, ".aflow", "flow.md"), "workflows (aflow)");
|
|
5696
5744
|
if (raw.startsWith("No ")) {
|
|
5697
5745
|
return { handled: true, output: raw };
|
|
5698
5746
|
}
|
|
@@ -5752,11 +5800,11 @@ async function handleToolsCommand(action, args, _ctx) {
|
|
|
5752
5800
|
}
|
|
5753
5801
|
const query = args.join(" ").toLowerCase();
|
|
5754
5802
|
const home2 = os18.homedir();
|
|
5755
|
-
const toolsFile =
|
|
5756
|
-
if (!
|
|
5803
|
+
const toolsFile = path20.join(home2, ".akit", "tools.md");
|
|
5804
|
+
if (!fs20.existsSync(toolsFile)) {
|
|
5757
5805
|
return { handled: true, output: pc6.dim(`No tools file found. Use 'npx @aman_asmuei/akit search ${args.join(" ")}' to search the registry.`) };
|
|
5758
5806
|
}
|
|
5759
|
-
const raw =
|
|
5807
|
+
const raw = fs20.readFileSync(toolsFile, "utf-8").trim();
|
|
5760
5808
|
const lines = raw.split("\n");
|
|
5761
5809
|
const matches = lines.filter((l) => l.toLowerCase().includes(query));
|
|
5762
5810
|
if (matches.length === 0) {
|
|
@@ -5769,7 +5817,7 @@ async function handleToolsCommand(action, args, _ctx) {
|
|
|
5769
5817
|
async function handleSkillsCommand(action, args, ctx) {
|
|
5770
5818
|
const home2 = os18.homedir();
|
|
5771
5819
|
if (!action) {
|
|
5772
|
-
const content = readEcosystemFile(
|
|
5820
|
+
const content = readEcosystemFile(path20.join(home2, ".askill", "skills.md"), "skills (askill)");
|
|
5773
5821
|
return { handled: true, output: content };
|
|
5774
5822
|
}
|
|
5775
5823
|
if (action === "install") {
|
|
@@ -5792,7 +5840,7 @@ async function handleSkillsCommand(action, args, ctx) {
|
|
|
5792
5840
|
}
|
|
5793
5841
|
const query = args.join(" ").toLowerCase();
|
|
5794
5842
|
const home3 = os18.homedir();
|
|
5795
|
-
const raw = readEcosystemFile(
|
|
5843
|
+
const raw = readEcosystemFile(path20.join(home3, ".askill", "skills.md"), "skills (askill)");
|
|
5796
5844
|
if (raw.startsWith("No ")) {
|
|
5797
5845
|
return { handled: true, output: raw };
|
|
5798
5846
|
}
|
|
@@ -5806,23 +5854,23 @@ async function handleSkillsCommand(action, args, ctx) {
|
|
|
5806
5854
|
if (action === "list") {
|
|
5807
5855
|
const autoOnly = args.includes("--auto");
|
|
5808
5856
|
if (autoOnly) {
|
|
5809
|
-
const logPath =
|
|
5857
|
+
const logPath = path20.join(os18.homedir(), ".aman-agent", "crystallization-log.json");
|
|
5810
5858
|
try {
|
|
5811
|
-
const content2 =
|
|
5859
|
+
const content2 = fs20.readFileSync(logPath, "utf-8");
|
|
5812
5860
|
const entries = JSON.parse(content2);
|
|
5813
5861
|
if (entries.length === 0) {
|
|
5814
5862
|
return { handled: true, output: pc6.dim("No crystallized skills yet.") };
|
|
5815
5863
|
}
|
|
5816
|
-
const suggestionsPath =
|
|
5864
|
+
const suggestionsPath = path20.join(os18.homedir(), ".aman-agent", "crystallization-suggestions.json");
|
|
5817
5865
|
let sugCounts = {};
|
|
5818
5866
|
try {
|
|
5819
|
-
const sc =
|
|
5867
|
+
const sc = fs20.readFileSync(suggestionsPath, "utf-8");
|
|
5820
5868
|
sugCounts = JSON.parse(sc);
|
|
5821
5869
|
} catch {
|
|
5822
5870
|
}
|
|
5823
5871
|
let versionCounts = {};
|
|
5824
5872
|
try {
|
|
5825
|
-
const skillsContent =
|
|
5873
|
+
const skillsContent = fs20.readFileSync(path20.join(os18.homedir(), ".askill", "skills.md"), "utf-8");
|
|
5826
5874
|
const versionRe = /^# (.+)\.v(\d+)$/gm;
|
|
5827
5875
|
let vMatch;
|
|
5828
5876
|
while ((vMatch = versionRe.exec(skillsContent)) !== null) {
|
|
@@ -5847,13 +5895,13 @@ async function handleSkillsCommand(action, args, ctx) {
|
|
|
5847
5895
|
return { handled: true, output: pc6.dim("No crystallized skills yet.") };
|
|
5848
5896
|
}
|
|
5849
5897
|
}
|
|
5850
|
-
const content = readEcosystemFile(
|
|
5898
|
+
const content = readEcosystemFile(path20.join(home2, ".askill", "skills.md"), "skills (askill)");
|
|
5851
5899
|
return { handled: true, output: content };
|
|
5852
5900
|
}
|
|
5853
5901
|
if (action === "crystallize") {
|
|
5854
|
-
const pmDir =
|
|
5902
|
+
const pmDir = path20.join(os18.homedir(), ".acore", "postmortems");
|
|
5855
5903
|
try {
|
|
5856
|
-
const files =
|
|
5904
|
+
const files = fs20.readdirSync(pmDir);
|
|
5857
5905
|
const jsonFiles = files.filter((f) => f.endsWith(".json")).sort().reverse();
|
|
5858
5906
|
if (jsonFiles.length === 0) {
|
|
5859
5907
|
return {
|
|
@@ -5862,7 +5910,7 @@ async function handleSkillsCommand(action, args, ctx) {
|
|
|
5862
5910
|
};
|
|
5863
5911
|
}
|
|
5864
5912
|
const latest = jsonFiles[0];
|
|
5865
|
-
const content =
|
|
5913
|
+
const content = fs20.readFileSync(path20.join(pmDir, latest), "utf-8");
|
|
5866
5914
|
const report = JSON.parse(content);
|
|
5867
5915
|
if (!report.crystallizationCandidates || report.crystallizationCandidates.length === 0) {
|
|
5868
5916
|
return {
|
|
@@ -5870,8 +5918,8 @@ async function handleSkillsCommand(action, args, ctx) {
|
|
|
5870
5918
|
output: pc6.dim(`No crystallization candidates in the most recent post-mortem (${latest}). Run a longer session or wait for the next auto-postmortem.`)
|
|
5871
5919
|
};
|
|
5872
5920
|
}
|
|
5873
|
-
const skillsMdPath =
|
|
5874
|
-
const logPath =
|
|
5921
|
+
const skillsMdPath = path20.join(os18.homedir(), ".askill", "skills.md");
|
|
5922
|
+
const logPath = path20.join(os18.homedir(), ".aman-agent", "crystallization-log.json");
|
|
5875
5923
|
const postmortemFilename = latest.replace(/\.json$/, ".md");
|
|
5876
5924
|
const lines = [
|
|
5877
5925
|
pc6.bold(`Found ${report.crystallizationCandidates.length} candidate(s) in ${latest}:`)
|
|
@@ -5930,7 +5978,7 @@ async function handleSkillsCommand(action, args, ctx) {
|
|
|
5930
5978
|
async function handleEvalCommand(action, args, ctx) {
|
|
5931
5979
|
const home2 = os18.homedir();
|
|
5932
5980
|
if (!action) {
|
|
5933
|
-
const content = readEcosystemFile(
|
|
5981
|
+
const content = readEcosystemFile(path20.join(home2, ".aeval", "eval.md"), "evaluation (aeval)");
|
|
5934
5982
|
return { handled: true, output: content };
|
|
5935
5983
|
}
|
|
5936
5984
|
if (action === "milestone") {
|
|
@@ -5942,10 +5990,10 @@ async function handleEvalCommand(action, args, ctx) {
|
|
|
5942
5990
|
return { handled: true, output };
|
|
5943
5991
|
}
|
|
5944
5992
|
if (action === "report") {
|
|
5945
|
-
const evalFile =
|
|
5993
|
+
const evalFile = path20.join(home2, ".aeval", "eval.md");
|
|
5946
5994
|
const lines = [pc6.bold("\u{1F4CA} Eval Report")];
|
|
5947
|
-
if (
|
|
5948
|
-
lines.push("",
|
|
5995
|
+
if (fs20.existsSync(evalFile)) {
|
|
5996
|
+
lines.push("", fs20.readFileSync(evalFile, "utf-8").trim());
|
|
5949
5997
|
} else {
|
|
5950
5998
|
lines.push("", pc6.dim("No eval log yet. Use /eval milestone <text> to start."));
|
|
5951
5999
|
}
|
|
@@ -6503,10 +6551,10 @@ function handleSave() {
|
|
|
6503
6551
|
}
|
|
6504
6552
|
function handleReset(action) {
|
|
6505
6553
|
const dirs = {
|
|
6506
|
-
config:
|
|
6507
|
-
memory:
|
|
6508
|
-
identity:
|
|
6509
|
-
rules:
|
|
6554
|
+
config: path20.join(os18.homedir(), ".aman-agent"),
|
|
6555
|
+
memory: path20.join(os18.homedir(), ".amem"),
|
|
6556
|
+
identity: path20.join(os18.homedir(), ".acore"),
|
|
6557
|
+
rules: path20.join(os18.homedir(), ".arules")
|
|
6510
6558
|
};
|
|
6511
6559
|
if (action === "help" || !action) {
|
|
6512
6560
|
return {
|
|
@@ -6531,15 +6579,15 @@ function handleReset(action) {
|
|
|
6531
6579
|
const removed = [];
|
|
6532
6580
|
for (const target of targets) {
|
|
6533
6581
|
const dir = dirs[target];
|
|
6534
|
-
if (
|
|
6535
|
-
|
|
6582
|
+
if (fs20.existsSync(dir)) {
|
|
6583
|
+
fs20.rmSync(dir, { recursive: true, force: true });
|
|
6536
6584
|
removed.push(target);
|
|
6537
6585
|
}
|
|
6538
6586
|
}
|
|
6539
6587
|
if (targets.includes("config")) {
|
|
6540
6588
|
const configDir2 = dirs.config;
|
|
6541
|
-
|
|
6542
|
-
|
|
6589
|
+
fs20.mkdirSync(configDir2, { recursive: true });
|
|
6590
|
+
fs20.writeFileSync(path20.join(configDir2, ".reconfig"), "", "utf-8");
|
|
6543
6591
|
}
|
|
6544
6592
|
if (removed.length === 0) {
|
|
6545
6593
|
return { handled: true, output: pc6.dim("Nothing to reset \u2014 directories don't exist.") };
|
|
@@ -6556,20 +6604,19 @@ function handleReset(action) {
|
|
|
6556
6604
|
function handleUpdate() {
|
|
6557
6605
|
try {
|
|
6558
6606
|
const current = execFileSync3("npm", ["view", "@aman_asmuei/aman-agent", "version"], { encoding: "utf-8" }).trim();
|
|
6559
|
-
const local = true ? "0.
|
|
6607
|
+
const local = true ? "0.32.0" : "unknown";
|
|
6560
6608
|
if (current === local) {
|
|
6561
6609
|
return { handled: true, output: `${pc6.green("Up to date")} \u2014 v${local}` };
|
|
6562
6610
|
}
|
|
6611
|
+
const isVendored = process.execPath.includes(path20.join(".aman-agent", "node"));
|
|
6612
|
+
const updateCmd = isVendored ? "aman-agent update" : "npm install -g @aman_asmuei/aman-agent@latest";
|
|
6563
6613
|
return {
|
|
6564
6614
|
handled: true,
|
|
6565
6615
|
output: [
|
|
6566
6616
|
`${pc6.yellow("Update available:")} v${local} \u2192 v${current}`,
|
|
6567
6617
|
"",
|
|
6568
6618
|
`Run this in your terminal:`,
|
|
6569
|
-
` ${pc6.bold(
|
|
6570
|
-
"",
|
|
6571
|
-
`Or use npx (always latest):`,
|
|
6572
|
-
` ${pc6.bold("npx @aman_asmuei/aman-agent@latest")}`
|
|
6619
|
+
` ${pc6.bold(updateCmd)}`
|
|
6573
6620
|
].join("\n")
|
|
6574
6621
|
};
|
|
6575
6622
|
} catch {
|
|
@@ -6577,10 +6624,7 @@ function handleUpdate() {
|
|
|
6577
6624
|
handled: true,
|
|
6578
6625
|
output: [
|
|
6579
6626
|
`To update, run in your terminal:`,
|
|
6580
|
-
` ${pc6.bold("npm install -g @aman_asmuei/aman-agent@latest")}
|
|
6581
|
-
"",
|
|
6582
|
-
`Or use npx (always latest):`,
|
|
6583
|
-
` ${pc6.bold("npx @aman_asmuei/aman-agent@latest")}`
|
|
6627
|
+
` ${pc6.bold("npm install -g @aman_asmuei/aman-agent@latest")}`
|
|
6584
6628
|
].join("\n")
|
|
6585
6629
|
};
|
|
6586
6630
|
}
|
|
@@ -6600,11 +6644,11 @@ function handleExportCommand() {
|
|
|
6600
6644
|
return { handled: true, exportConversation: true };
|
|
6601
6645
|
}
|
|
6602
6646
|
function handleDebugCommand() {
|
|
6603
|
-
const logPath =
|
|
6604
|
-
if (!
|
|
6647
|
+
const logPath = path20.join(os18.homedir(), ".aman-agent", "debug.log");
|
|
6648
|
+
if (!fs20.existsSync(logPath)) {
|
|
6605
6649
|
return { handled: true, output: pc6.dim("No debug log found.") };
|
|
6606
6650
|
}
|
|
6607
|
-
const content =
|
|
6651
|
+
const content = fs20.readFileSync(logPath, "utf-8");
|
|
6608
6652
|
const lines = content.trim().split("\n");
|
|
6609
6653
|
const last20 = lines.slice(-20).join("\n");
|
|
6610
6654
|
return { handled: true, output: pc6.bold("Debug Log (last 20 entries):\n") + pc6.dim(last20) };
|
|
@@ -6884,7 +6928,7 @@ ${text3}` };
|
|
|
6884
6928
|
};
|
|
6885
6929
|
}
|
|
6886
6930
|
function handleProfileCommand(action, args) {
|
|
6887
|
-
const profilesDir =
|
|
6931
|
+
const profilesDir = path20.join(os18.homedir(), ".acore", "profiles");
|
|
6888
6932
|
if (action === "me") {
|
|
6889
6933
|
const user = loadUserIdentity();
|
|
6890
6934
|
if (!user) {
|
|
@@ -6952,8 +6996,8 @@ ${pc6.dim("Edit with: /profile edit")}` };
|
|
|
6952
6996
|
};
|
|
6953
6997
|
}
|
|
6954
6998
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
6955
|
-
const profileDir =
|
|
6956
|
-
if (
|
|
6999
|
+
const profileDir = path20.join(profilesDir, slug);
|
|
7000
|
+
if (fs20.existsSync(profileDir)) {
|
|
6957
7001
|
return { handled: true, output: pc6.yellow(`Profile already exists: ${slug}`) };
|
|
6958
7002
|
}
|
|
6959
7003
|
const builtIn = BUILT_IN_PROFILES.find((t) => t.name === slug);
|
|
@@ -6969,16 +7013,16 @@ ${pc6.dim("Edit with: /profile edit")}` };
|
|
|
6969
7013
|
Use: aman-agent --profile ${slug}`
|
|
6970
7014
|
};
|
|
6971
7015
|
}
|
|
6972
|
-
|
|
6973
|
-
const globalCore =
|
|
6974
|
-
if (
|
|
6975
|
-
let content =
|
|
7016
|
+
fs20.mkdirSync(profileDir, { recursive: true });
|
|
7017
|
+
const globalCore = path20.join(os18.homedir(), ".acore", "core.md");
|
|
7018
|
+
if (fs20.existsSync(globalCore)) {
|
|
7019
|
+
let content = fs20.readFileSync(globalCore, "utf-8");
|
|
6976
7020
|
const aiName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
6977
7021
|
content = content.replace(/^# .+$/m, `# ${aiName}`);
|
|
6978
|
-
|
|
7022
|
+
fs20.writeFileSync(path20.join(profileDir, "core.md"), content, "utf-8");
|
|
6979
7023
|
} else {
|
|
6980
7024
|
const aiName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
6981
|
-
|
|
7025
|
+
fs20.writeFileSync(path20.join(profileDir, "core.md"), `# ${aiName}
|
|
6982
7026
|
|
|
6983
7027
|
## Identity
|
|
6984
7028
|
- Role: ${aiName} is your AI companion
|
|
@@ -6991,7 +7035,7 @@ ${pc6.dim("Edit with: /profile edit")}` };
|
|
|
6991
7035
|
return {
|
|
6992
7036
|
handled: true,
|
|
6993
7037
|
output: pc6.green(`Profile created: ${slug}`) + `
|
|
6994
|
-
Edit: ${
|
|
7038
|
+
Edit: ${path20.join(profileDir, "core.md")}
|
|
6995
7039
|
Use: aman-agent --profile ${slug}
|
|
6996
7040
|
|
|
6997
7041
|
${pc6.dim("Add rules.md or skills.md for profile-specific overrides.")}`
|
|
@@ -7000,9 +7044,9 @@ ${pc6.dim("Edit with: /profile edit")}` };
|
|
|
7000
7044
|
case "show": {
|
|
7001
7045
|
const name = args[0];
|
|
7002
7046
|
if (!name) return { handled: true, output: pc6.yellow("Usage: /profile show <name>") };
|
|
7003
|
-
const profileDir =
|
|
7004
|
-
if (!
|
|
7005
|
-
const files =
|
|
7047
|
+
const profileDir = path20.join(profilesDir, name);
|
|
7048
|
+
if (!fs20.existsSync(profileDir)) return { handled: true, output: pc6.red(`Profile not found: ${name}`) };
|
|
7049
|
+
const files = fs20.readdirSync(profileDir).filter((f) => f.endsWith(".md"));
|
|
7006
7050
|
const lines = files.map((f) => ` ${f}`);
|
|
7007
7051
|
return { handled: true, output: `Profile: ${pc6.bold(name)}
|
|
7008
7052
|
Files:
|
|
@@ -7011,9 +7055,9 @@ ${lines.join("\n")}` };
|
|
|
7011
7055
|
case "delete": {
|
|
7012
7056
|
const name = args[0];
|
|
7013
7057
|
if (!name) return { handled: true, output: pc6.yellow("Usage: /profile delete <name>") };
|
|
7014
|
-
const profileDir =
|
|
7015
|
-
if (!
|
|
7016
|
-
|
|
7058
|
+
const profileDir = path20.join(profilesDir, name);
|
|
7059
|
+
if (!fs20.existsSync(profileDir)) return { handled: true, output: pc6.red(`Profile not found: ${name}`) };
|
|
7060
|
+
fs20.rmSync(profileDir, { recursive: true });
|
|
7017
7061
|
return { handled: true, output: pc6.dim(`Profile deleted: ${name}`) };
|
|
7018
7062
|
}
|
|
7019
7063
|
case "help":
|
|
@@ -7231,10 +7275,10 @@ function handleShowcaseCommand(action, args) {
|
|
|
7231
7275
|
Or place it as a sibling directory to aman-agent.`
|
|
7232
7276
|
};
|
|
7233
7277
|
}
|
|
7234
|
-
const corePath =
|
|
7278
|
+
const corePath = path20.join(os18.homedir(), ".acore", "core.md");
|
|
7235
7279
|
let currentShowcase = null;
|
|
7236
|
-
if (
|
|
7237
|
-
const content =
|
|
7280
|
+
if (fs20.existsSync(corePath)) {
|
|
7281
|
+
const content = fs20.readFileSync(corePath, "utf-8");
|
|
7238
7282
|
const nameMatch = content.match(/^# (.+)/m);
|
|
7239
7283
|
if (nameMatch) {
|
|
7240
7284
|
const coreName = nameMatch[1].trim().toLowerCase();
|
|
@@ -7632,9 +7676,9 @@ init_logger();
|
|
|
7632
7676
|
|
|
7633
7677
|
// src/skill-engine.ts
|
|
7634
7678
|
init_logger();
|
|
7635
|
-
import
|
|
7679
|
+
import fs21 from "fs";
|
|
7636
7680
|
import fsp from "fs/promises";
|
|
7637
|
-
import
|
|
7681
|
+
import path21 from "path";
|
|
7638
7682
|
import os19 from "os";
|
|
7639
7683
|
var SKILL_TRIGGERS = {
|
|
7640
7684
|
testing: ["test", "spec", "coverage", "tdd", "jest", "vitest", "mocha", "assert", "mock", "stub", "fixture", "e2e", "integration test", "unit test"],
|
|
@@ -7664,20 +7708,20 @@ async function loadRuntimeTriggers(skillsMdPath) {
|
|
|
7664
7708
|
return /* @__PURE__ */ new Map();
|
|
7665
7709
|
}
|
|
7666
7710
|
}
|
|
7667
|
-
var LEVEL_FILE =
|
|
7711
|
+
var LEVEL_FILE = path21.join(os19.homedir(), ".aman-agent", "skill-levels.json");
|
|
7668
7712
|
function loadSkillLevels() {
|
|
7669
7713
|
try {
|
|
7670
|
-
if (
|
|
7671
|
-
return JSON.parse(
|
|
7714
|
+
if (fs21.existsSync(LEVEL_FILE)) {
|
|
7715
|
+
return JSON.parse(fs21.readFileSync(LEVEL_FILE, "utf-8"));
|
|
7672
7716
|
}
|
|
7673
7717
|
} catch {
|
|
7674
7718
|
}
|
|
7675
7719
|
return {};
|
|
7676
7720
|
}
|
|
7677
7721
|
function saveSkillLevels(levels) {
|
|
7678
|
-
const dir =
|
|
7679
|
-
if (!
|
|
7680
|
-
|
|
7722
|
+
const dir = path21.dirname(LEVEL_FILE);
|
|
7723
|
+
if (!fs21.existsSync(dir)) fs21.mkdirSync(dir, { recursive: true });
|
|
7724
|
+
fs21.writeFileSync(LEVEL_FILE, JSON.stringify(levels, null, 2), "utf-8");
|
|
7681
7725
|
}
|
|
7682
7726
|
function computeLevel(activations) {
|
|
7683
7727
|
if (activations >= 50) return { level: 5, label: "Expert" };
|
|
@@ -7904,7 +7948,7 @@ async function autoTriggerSkills(userInput, mcpManager) {
|
|
|
7904
7948
|
const result = await mcpManager.callTool("skill_list", {});
|
|
7905
7949
|
const skills = JSON.parse(result);
|
|
7906
7950
|
const installed = skills.filter((s) => s.installed).map((s) => s.name);
|
|
7907
|
-
const skillsMdPath =
|
|
7951
|
+
const skillsMdPath = path21.join(os19.homedir(), ".askill", "skills.md");
|
|
7908
7952
|
const runtimeTriggers = await loadRuntimeTriggers(skillsMdPath);
|
|
7909
7953
|
if (installed.length === 0 && runtimeTriggers.size === 0) return "";
|
|
7910
7954
|
const matched = matchSkillsSemantic(userInput, installed, runtimeTriggers);
|
|
@@ -8358,8 +8402,8 @@ function humanizeError(message) {
|
|
|
8358
8402
|
}
|
|
8359
8403
|
|
|
8360
8404
|
// src/hints.ts
|
|
8361
|
-
import
|
|
8362
|
-
import
|
|
8405
|
+
import fs22 from "fs";
|
|
8406
|
+
import path22 from "path";
|
|
8363
8407
|
import os20 from "os";
|
|
8364
8408
|
var HINTS = [
|
|
8365
8409
|
{
|
|
@@ -8398,11 +8442,11 @@ function getHint(state, ctx) {
|
|
|
8398
8442
|
}
|
|
8399
8443
|
return null;
|
|
8400
8444
|
}
|
|
8401
|
-
var HINTS_FILE =
|
|
8445
|
+
var HINTS_FILE = path22.join(os20.homedir(), ".aman-agent", "hints-seen.json");
|
|
8402
8446
|
function loadShownHints() {
|
|
8403
8447
|
try {
|
|
8404
|
-
if (
|
|
8405
|
-
const data = JSON.parse(
|
|
8448
|
+
if (fs22.existsSync(HINTS_FILE)) {
|
|
8449
|
+
const data = JSON.parse(fs22.readFileSync(HINTS_FILE, "utf-8"));
|
|
8406
8450
|
return new Set(Array.isArray(data) ? data : []);
|
|
8407
8451
|
}
|
|
8408
8452
|
} catch {
|
|
@@ -8411,9 +8455,9 @@ function loadShownHints() {
|
|
|
8411
8455
|
}
|
|
8412
8456
|
function saveShownHints(shown) {
|
|
8413
8457
|
try {
|
|
8414
|
-
const dir =
|
|
8415
|
-
|
|
8416
|
-
|
|
8458
|
+
const dir = path22.dirname(HINTS_FILE);
|
|
8459
|
+
fs22.mkdirSync(dir, { recursive: true });
|
|
8460
|
+
fs22.writeFileSync(HINTS_FILE, JSON.stringify([...shown]), "utf-8");
|
|
8417
8461
|
} catch {
|
|
8418
8462
|
}
|
|
8419
8463
|
}
|
|
@@ -8680,9 +8724,9 @@ ${task.result}`
|
|
|
8680
8724
|
}
|
|
8681
8725
|
if (cmdResult.exportConversation) {
|
|
8682
8726
|
try {
|
|
8683
|
-
const exportDir =
|
|
8684
|
-
|
|
8685
|
-
const exportPath =
|
|
8727
|
+
const exportDir = path23.join(os21.homedir(), ".aman-agent", "exports");
|
|
8728
|
+
fs23.mkdirSync(exportDir, { recursive: true });
|
|
8729
|
+
const exportPath = path23.join(exportDir, `${sessionId}.md`);
|
|
8686
8730
|
const lines = [
|
|
8687
8731
|
`# Conversation \u2014 ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
8688
8732
|
`**Model:** ${model}`,
|
|
@@ -8696,7 +8740,7 @@ ${task.result}`
|
|
|
8696
8740
|
lines.push(`${label} ${msg.content}`, "");
|
|
8697
8741
|
}
|
|
8698
8742
|
}
|
|
8699
|
-
|
|
8743
|
+
fs23.writeFileSync(exportPath, lines.join("\n"), "utf-8");
|
|
8700
8744
|
console.log(pc7.green(`Exported to ${exportPath}`));
|
|
8701
8745
|
} catch {
|
|
8702
8746
|
console.log(pc7.red("Failed to export conversation."));
|
|
@@ -8822,25 +8866,25 @@ ${knowledgeItem.content}
|
|
|
8822
8866
|
for (const match of filePathMatches) {
|
|
8823
8867
|
let filePath = match[1];
|
|
8824
8868
|
if (filePath.startsWith("~/")) {
|
|
8825
|
-
filePath =
|
|
8869
|
+
filePath = path23.join(os21.homedir(), filePath.slice(2));
|
|
8826
8870
|
}
|
|
8827
|
-
if (!
|
|
8828
|
-
const ext =
|
|
8871
|
+
if (!fs23.existsSync(filePath) || !fs23.statSync(filePath).isFile()) continue;
|
|
8872
|
+
const ext = path23.extname(filePath).toLowerCase();
|
|
8829
8873
|
if (imageExts.has(ext)) {
|
|
8830
8874
|
try {
|
|
8831
|
-
const stat =
|
|
8875
|
+
const stat = fs23.statSync(filePath);
|
|
8832
8876
|
if (stat.size > maxImageBytes) {
|
|
8833
|
-
process.stdout.write(pc7.yellow(` [skipped: ${
|
|
8877
|
+
process.stdout.write(pc7.yellow(` [skipped: ${path23.basename(filePath)} \u2014 exceeds 20MB limit]
|
|
8834
8878
|
`));
|
|
8835
8879
|
continue;
|
|
8836
8880
|
}
|
|
8837
|
-
const data =
|
|
8881
|
+
const data = fs23.readFileSync(filePath).toString("base64");
|
|
8838
8882
|
const mediaType = mimeMap[ext] || "image/png";
|
|
8839
8883
|
imageBlocks.push({
|
|
8840
8884
|
type: "image",
|
|
8841
8885
|
source: { type: "base64", media_type: mediaType, data }
|
|
8842
8886
|
});
|
|
8843
|
-
process.stdout.write(pc7.dim(` [attached image: ${
|
|
8887
|
+
process.stdout.write(pc7.dim(` [attached image: ${path23.basename(filePath)} (${(stat.size / 1024).toFixed(1)}KB)]
|
|
8844
8888
|
`));
|
|
8845
8889
|
} catch {
|
|
8846
8890
|
process.stdout.write(pc7.dim(` [could not read image: ${filePath}]
|
|
@@ -8848,7 +8892,7 @@ ${knowledgeItem.content}
|
|
|
8848
8892
|
}
|
|
8849
8893
|
} else if (textExts.has(ext) || ext === "") {
|
|
8850
8894
|
try {
|
|
8851
|
-
const content =
|
|
8895
|
+
const content = fs23.readFileSync(filePath, "utf-8");
|
|
8852
8896
|
const maxChars = 5e4;
|
|
8853
8897
|
const trimmed = content.length > maxChars ? content.slice(0, maxChars) + `
|
|
8854
8898
|
|
|
@@ -8858,7 +8902,7 @@ ${knowledgeItem.content}
|
|
|
8858
8902
|
<file path="${filePath}" size="${content.length} chars">
|
|
8859
8903
|
${trimmed}
|
|
8860
8904
|
</file>`;
|
|
8861
|
-
process.stdout.write(pc7.dim(` [attached: ${
|
|
8905
|
+
process.stdout.write(pc7.dim(` [attached: ${path23.basename(filePath)} (${(content.length / 1024).toFixed(1)}KB)]
|
|
8862
8906
|
`));
|
|
8863
8907
|
} catch {
|
|
8864
8908
|
process.stdout.write(pc7.dim(` [could not read: ${filePath}]
|
|
@@ -8867,7 +8911,7 @@ ${trimmed}
|
|
|
8867
8911
|
} else if (docExts.has(ext)) {
|
|
8868
8912
|
if (mcpManager) {
|
|
8869
8913
|
try {
|
|
8870
|
-
process.stdout.write(pc7.dim(` [converting: ${
|
|
8914
|
+
process.stdout.write(pc7.dim(` [converting: ${path23.basename(filePath)}...]
|
|
8871
8915
|
`));
|
|
8872
8916
|
const converted = await mcpManager.callTool("doc_convert", { path: filePath });
|
|
8873
8917
|
if (converted && !converted.startsWith("Error") && !converted.includes("Could not convert")) {
|
|
@@ -8876,7 +8920,7 @@ ${trimmed}
|
|
|
8876
8920
|
<file path="${filePath}" format="${ext}">
|
|
8877
8921
|
${converted.slice(0, 5e4)}
|
|
8878
8922
|
</file>`;
|
|
8879
|
-
process.stdout.write(pc7.dim(` [attached: ${
|
|
8923
|
+
process.stdout.write(pc7.dim(` [attached: ${path23.basename(filePath)} (converted from ${ext})]
|
|
8880
8924
|
`));
|
|
8881
8925
|
} else {
|
|
8882
8926
|
textContent += `
|
|
@@ -8888,7 +8932,7 @@ ${converted}
|
|
|
8888
8932
|
`));
|
|
8889
8933
|
}
|
|
8890
8934
|
} catch {
|
|
8891
|
-
process.stdout.write(pc7.dim(` [could not convert: ${
|
|
8935
|
+
process.stdout.write(pc7.dim(` [could not convert: ${path23.basename(filePath)}]
|
|
8892
8936
|
`));
|
|
8893
8937
|
}
|
|
8894
8938
|
} else {
|
|
@@ -9280,7 +9324,7 @@ ${result2.response}` : `[${input2.profile}] failed: ${result2.error}`;
|
|
|
9280
9324
|
}
|
|
9281
9325
|
if (hooksConfig?.featureHints) {
|
|
9282
9326
|
hintState.turnCount++;
|
|
9283
|
-
const hasWorkflows =
|
|
9327
|
+
const hasWorkflows = fs23.existsSync(path23.join(os21.homedir(), ".aflow", "flow.md"));
|
|
9284
9328
|
const memoryCount = memoryTokens > 0 ? Math.floor(memoryTokens / 5) : 0;
|
|
9285
9329
|
const hint = getHint(hintState, { hasWorkflows, memoryCount });
|
|
9286
9330
|
if (hint) {
|
|
@@ -9326,9 +9370,8 @@ async function saveConversationToMemory(messages, sessionId) {
|
|
|
9326
9370
|
}
|
|
9327
9371
|
|
|
9328
9372
|
// src/index.ts
|
|
9329
|
-
import
|
|
9330
|
-
import
|
|
9331
|
-
import os22 from "os";
|
|
9373
|
+
import fs24 from "fs";
|
|
9374
|
+
import path24 from "path";
|
|
9332
9375
|
|
|
9333
9376
|
// src/presets.ts
|
|
9334
9377
|
var PRESETS = {
|
|
@@ -9542,9 +9585,12 @@ var Inbox = class {
|
|
|
9542
9585
|
// package.json
|
|
9543
9586
|
var package_default = {
|
|
9544
9587
|
name: "@aman_asmuei/aman-agent",
|
|
9545
|
-
version: "0.
|
|
9588
|
+
version: "0.32.0",
|
|
9546
9589
|
description: "Your AI companion, running locally \u2014 powered by the aman ecosystem",
|
|
9547
9590
|
type: "module",
|
|
9591
|
+
engines: {
|
|
9592
|
+
node: ">=18.0.0"
|
|
9593
|
+
},
|
|
9548
9594
|
bin: {
|
|
9549
9595
|
"aman-agent": "./bin/aman-agent.js"
|
|
9550
9596
|
},
|
|
@@ -9832,9 +9878,9 @@ async function runServe(opts) {
|
|
|
9832
9878
|
|
|
9833
9879
|
// src/index.ts
|
|
9834
9880
|
async function autoDetectConfig() {
|
|
9835
|
-
const reconfigMarker =
|
|
9836
|
-
if (
|
|
9837
|
-
|
|
9881
|
+
const reconfigMarker = path24.join(homeDir(), ".reconfig");
|
|
9882
|
+
if (fs24.existsSync(reconfigMarker)) {
|
|
9883
|
+
fs24.unlinkSync(reconfigMarker);
|
|
9838
9884
|
return null;
|
|
9839
9885
|
}
|
|
9840
9886
|
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
@@ -9863,11 +9909,10 @@ async function autoDetectConfig() {
|
|
|
9863
9909
|
return null;
|
|
9864
9910
|
}
|
|
9865
9911
|
function bootstrapEcosystem() {
|
|
9866
|
-
const
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
fs23.writeFileSync(corePath, [
|
|
9912
|
+
const corePath = path24.join(identityDir(), "core.md");
|
|
9913
|
+
if (fs24.existsSync(corePath)) return false;
|
|
9914
|
+
fs24.mkdirSync(identityDir(), { recursive: true });
|
|
9915
|
+
fs24.writeFileSync(corePath, [
|
|
9871
9916
|
"# Aman",
|
|
9872
9917
|
"",
|
|
9873
9918
|
"## Personality",
|
|
@@ -9879,11 +9924,10 @@ function bootstrapEcosystem() {
|
|
|
9879
9924
|
"## Session",
|
|
9880
9925
|
"_New companion \u2014 no prior sessions._"
|
|
9881
9926
|
].join("\n"), "utf-8");
|
|
9882
|
-
const
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
fs23.writeFileSync(rulesPath, [
|
|
9927
|
+
const rulesPath = path24.join(rulesDir(), "rules.md");
|
|
9928
|
+
if (!fs24.existsSync(rulesPath)) {
|
|
9929
|
+
fs24.mkdirSync(rulesDir(), { recursive: true });
|
|
9930
|
+
fs24.writeFileSync(rulesPath, [
|
|
9887
9931
|
"# Guardrails",
|
|
9888
9932
|
"",
|
|
9889
9933
|
"## safety",
|
|
@@ -9895,22 +9939,20 @@ function bootstrapEcosystem() {
|
|
|
9895
9939
|
"- Respect the user's preferences stored in memory"
|
|
9896
9940
|
].join("\n"), "utf-8");
|
|
9897
9941
|
}
|
|
9898
|
-
const
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9902
|
-
fs23.writeFileSync(flowPath, "# Workflows\n\n_No workflows defined yet. Use /workflows add to create one._\n", "utf-8");
|
|
9942
|
+
const flowPath = path24.join(workflowsDir(), "flow.md");
|
|
9943
|
+
if (!fs24.existsSync(flowPath)) {
|
|
9944
|
+
fs24.mkdirSync(workflowsDir(), { recursive: true });
|
|
9945
|
+
fs24.writeFileSync(flowPath, "# Workflows\n\n_No workflows defined yet. Use /workflows add to create one._\n", "utf-8");
|
|
9903
9946
|
}
|
|
9904
|
-
const
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
fs23.writeFileSync(skillPath, "# Skills\n\n_No skills installed yet. Use /skills install to add domain expertise._\n", "utf-8");
|
|
9947
|
+
const skillPath = path24.join(skillsDir(), "skills.md");
|
|
9948
|
+
if (!fs24.existsSync(skillPath)) {
|
|
9949
|
+
fs24.mkdirSync(skillsDir(), { recursive: true });
|
|
9950
|
+
fs24.writeFileSync(skillPath, "# Skills\n\n_No skills installed yet. Use /skills install to add domain expertise._\n", "utf-8");
|
|
9909
9951
|
}
|
|
9910
9952
|
return true;
|
|
9911
9953
|
}
|
|
9912
9954
|
var program = new Command();
|
|
9913
|
-
program.name("aman-agent").description("Your AI companion, running locally").version("0.
|
|
9955
|
+
program.name("aman-agent").description("Your AI companion, running locally").version("0.32.0").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) => {
|
|
9914
9956
|
p4.intro(pc9.bold("aman agent") + pc9.dim(" \u2014 your AI companion"));
|
|
9915
9957
|
let config = loadConfig();
|
|
9916
9958
|
if (!config) {
|
|
@@ -9922,6 +9964,11 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
9922
9964
|
p4.log.info(pc9.dim("Change anytime with /reset config"));
|
|
9923
9965
|
saveConfig(config);
|
|
9924
9966
|
} else {
|
|
9967
|
+
if (!process.stdin.isTTY) {
|
|
9968
|
+
console.error("Error: No LLM provider configured.");
|
|
9969
|
+
console.error("Set ANTHROPIC_API_KEY or OPENAI_API_KEY, or run interactively: aman-agent");
|
|
9970
|
+
process.exit(1);
|
|
9971
|
+
}
|
|
9925
9972
|
p4.log.info("First-time setup \u2014 configure your LLM connection.");
|
|
9926
9973
|
const provider = await p4.select({
|
|
9927
9974
|
message: "LLM provider",
|
|
@@ -10134,6 +10181,15 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
10134
10181
|
const model = options.model || config.model;
|
|
10135
10182
|
const s = p4.spinner();
|
|
10136
10183
|
s.start("Loading ecosystem");
|
|
10184
|
+
const migration = migrateIfNeeded();
|
|
10185
|
+
if (migration.migrated.length > 0) {
|
|
10186
|
+
for (const dir of migration.migrated) {
|
|
10187
|
+
p4.log.info(`Migrated \u2192 ~/.aman-agent/${dir}/`);
|
|
10188
|
+
}
|
|
10189
|
+
}
|
|
10190
|
+
process.env.ACORE_HOME = identityDir();
|
|
10191
|
+
process.env.ARULES_HOME = rulesDir();
|
|
10192
|
+
process.env.AMEM_DIR = memoryDir();
|
|
10137
10193
|
const isFirstRun = bootstrapEcosystem();
|
|
10138
10194
|
if (!hasUserIdentity()) {
|
|
10139
10195
|
s.stop("Ecosystem loaded");
|
|
@@ -10251,19 +10307,18 @@ program.command("init").description("Set up your AI companion with a guided wiza
|
|
|
10251
10307
|
});
|
|
10252
10308
|
if (p4.isCancel(preset)) process.exit(0);
|
|
10253
10309
|
const result = applyPreset(preset, name || "Aman");
|
|
10254
|
-
|
|
10255
|
-
|
|
10256
|
-
fs23.writeFileSync(path23.join(home2, ".acore", "core.md"), result.coreMd, "utf-8");
|
|
10310
|
+
fs24.mkdirSync(identityDir(), { recursive: true });
|
|
10311
|
+
fs24.writeFileSync(path24.join(identityDir(), "core.md"), result.coreMd, "utf-8");
|
|
10257
10312
|
p4.log.success(`Identity created \u2014 ${PRESETS[preset].identity.personality.split(".")[0].toLowerCase()}`);
|
|
10258
10313
|
if (result.rulesMd) {
|
|
10259
|
-
|
|
10260
|
-
|
|
10314
|
+
fs24.mkdirSync(rulesDir(), { recursive: true });
|
|
10315
|
+
fs24.writeFileSync(path24.join(rulesDir(), "rules.md"), result.rulesMd, "utf-8");
|
|
10261
10316
|
const ruleCount = (result.rulesMd.match(/^- /gm) || []).length;
|
|
10262
10317
|
p4.log.success(`${ruleCount} rules set`);
|
|
10263
10318
|
}
|
|
10264
10319
|
if (result.flowMd) {
|
|
10265
|
-
|
|
10266
|
-
|
|
10320
|
+
fs24.mkdirSync(workflowsDir(), { recursive: true });
|
|
10321
|
+
fs24.writeFileSync(path24.join(workflowsDir(), "flow.md"), result.flowMd, "utf-8");
|
|
10267
10322
|
const wfCount = (result.flowMd.match(/^## /gm) || []).length;
|
|
10268
10323
|
p4.log.success(`${wfCount} workflow${wfCount > 1 ? "s" : ""} added`);
|
|
10269
10324
|
}
|
|
@@ -10292,5 +10347,61 @@ program.command("serve").description("Run aman-agent as a local MCP server other
|
|
|
10292
10347
|
process.exit(1);
|
|
10293
10348
|
}
|
|
10294
10349
|
});
|
|
10350
|
+
program.command("setup").description("Run the full configuration wizard (provider, identity, presets)").action(async () => {
|
|
10351
|
+
p4.intro(pc9.bold("aman agent setup") + pc9.dim(" \u2014 full configuration wizard"));
|
|
10352
|
+
const reconfigPath = path24.join(homeDir(), ".reconfig");
|
|
10353
|
+
fs24.mkdirSync(homeDir(), { recursive: true });
|
|
10354
|
+
fs24.writeFileSync(reconfigPath, "", "utf-8");
|
|
10355
|
+
p4.log.info("Configuration reset. Restart aman-agent to complete setup.");
|
|
10356
|
+
});
|
|
10357
|
+
program.command("update").description("Update aman-agent to the latest version").action(async () => {
|
|
10358
|
+
const { execFileSync: execFileSync4 } = await import("child_process");
|
|
10359
|
+
const isVendored = process.execPath.includes(path24.join(".aman-agent", "node"));
|
|
10360
|
+
if (isVendored) {
|
|
10361
|
+
const npmPath = path24.join(homeDir(), "node", "bin", "npm");
|
|
10362
|
+
console.log("Updating aman-agent...");
|
|
10363
|
+
try {
|
|
10364
|
+
execFileSync4(npmPath, ["install", "-g", "@aman_asmuei/aman-agent@latest"], {
|
|
10365
|
+
stdio: "inherit",
|
|
10366
|
+
env: { ...process.env, PREFIX: homeDir() }
|
|
10367
|
+
});
|
|
10368
|
+
console.log("\u2713 Updated successfully.");
|
|
10369
|
+
} catch {
|
|
10370
|
+
console.error("Update failed. Try manually: npm install -g @aman_asmuei/aman-agent@latest");
|
|
10371
|
+
process.exit(1);
|
|
10372
|
+
}
|
|
10373
|
+
} else {
|
|
10374
|
+
console.log("Updating via npm...");
|
|
10375
|
+
try {
|
|
10376
|
+
execFileSync4("npm", ["install", "-g", "@aman_asmuei/aman-agent@latest"], {
|
|
10377
|
+
stdio: "inherit"
|
|
10378
|
+
});
|
|
10379
|
+
console.log("\u2713 Updated successfully.");
|
|
10380
|
+
} catch {
|
|
10381
|
+
console.error("Update failed. Try manually: npm install -g @aman_asmuei/aman-agent@latest");
|
|
10382
|
+
process.exit(1);
|
|
10383
|
+
}
|
|
10384
|
+
}
|
|
10385
|
+
});
|
|
10386
|
+
program.command("uninstall").description("Remove aman-agent and all its data").action(async () => {
|
|
10387
|
+
const home2 = homeDir();
|
|
10388
|
+
if (!process.stdin.isTTY) {
|
|
10389
|
+
fs24.rmSync(home2, { recursive: true, force: true });
|
|
10390
|
+
console.log("\u2713 Removed " + home2);
|
|
10391
|
+
return;
|
|
10392
|
+
}
|
|
10393
|
+
const confirm3 = await p4.confirm({
|
|
10394
|
+
message: `This will delete ${home2} and all your data (memory, identity, config). Continue?`
|
|
10395
|
+
});
|
|
10396
|
+
if (!confirm3 || p4.isCancel(confirm3)) {
|
|
10397
|
+
console.log("Cancelled.");
|
|
10398
|
+
return;
|
|
10399
|
+
}
|
|
10400
|
+
fs24.rmSync(home2, { recursive: true, force: true });
|
|
10401
|
+
console.log("\u2713 Removed " + home2);
|
|
10402
|
+
console.log("");
|
|
10403
|
+
console.log("To complete uninstall, remove the PATH line from your shell config:");
|
|
10404
|
+
console.log(' Remove: export PATH="$HOME/.aman-agent/bin:$PATH"');
|
|
10405
|
+
});
|
|
10295
10406
|
program.parse();
|
|
10296
10407
|
//# sourceMappingURL=index.js.map
|