@aman_asmuei/aman-agent 0.31.0 → 0.33.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 CHANGED
@@ -8,23 +8,82 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
+ // src/token-budget.ts
12
+ function estimateTokens(text3) {
13
+ return Math.round(text3.split(/\s+/).filter(Boolean).length * 1.3);
14
+ }
15
+ function buildBudgetedPrompt(components, maxTokens = 8e3) {
16
+ const included = [];
17
+ const truncated = [];
18
+ const parts = [];
19
+ let totalTokens = 0;
20
+ const sorted = [...components].sort((a, b) => {
21
+ const aPri = PRIORITIES.indexOf(a.name);
22
+ const bPri = PRIORITIES.indexOf(b.name);
23
+ return (aPri === -1 ? 99 : aPri) - (bPri === -1 ? 99 : bPri);
24
+ });
25
+ for (const comp of sorted) {
26
+ if (totalTokens + comp.tokens <= maxTokens) {
27
+ parts.push(comp.content);
28
+ included.push(comp.name);
29
+ totalTokens += comp.tokens;
30
+ } else {
31
+ const halfContent = comp.content.slice(0, Math.floor(comp.content.length / 2));
32
+ const halfTokens = estimateTokens(halfContent);
33
+ if (totalTokens + halfTokens <= maxTokens) {
34
+ parts.push(halfContent + "\n\n[... truncated for context budget ...]");
35
+ included.push(comp.name + " (partial)");
36
+ totalTokens += halfTokens;
37
+ } else {
38
+ truncated.push(comp.name);
39
+ }
40
+ }
41
+ }
42
+ return {
43
+ prompt: parts.join("\n\n---\n\n"),
44
+ included,
45
+ truncated,
46
+ totalTokens
47
+ };
48
+ }
49
+ var PRIORITIES;
50
+ var init_token_budget = __esm({
51
+ "src/token-budget.ts"() {
52
+ "use strict";
53
+ PRIORITIES = [
54
+ "identity",
55
+ // core.md — always include
56
+ "user",
57
+ // user.md — user profile, always include
58
+ "guardrails",
59
+ // rules.md — safety critical
60
+ "workflows",
61
+ // flow.md — behavioral
62
+ "tools",
63
+ // kit.md — capabilities
64
+ "skills"
65
+ // skills.md — can be truncated
66
+ ];
67
+ }
68
+ });
69
+
11
70
  // src/logger.ts
12
- import fs4 from "fs";
13
- import path4 from "path";
71
+ import fs5 from "fs";
72
+ import path5 from "path";
14
73
  import os4 from "os";
15
74
  function ensureDir() {
16
- if (!fs4.existsSync(LOG_DIR)) {
17
- fs4.mkdirSync(LOG_DIR, { recursive: true });
75
+ if (!fs5.existsSync(LOG_DIR)) {
76
+ fs5.mkdirSync(LOG_DIR, { recursive: true });
18
77
  }
19
78
  }
20
79
  function maybeRotate() {
21
80
  try {
22
- if (!fs4.existsSync(LOG_PATH)) return;
23
- const stat = fs4.statSync(LOG_PATH);
81
+ if (!fs5.existsSync(LOG_PATH)) return;
82
+ const stat = fs5.statSync(LOG_PATH);
24
83
  if (stat.size >= MAX_LOG_SIZE) {
25
84
  const backupPath = LOG_PATH + ".1";
26
- if (fs4.existsSync(backupPath)) fs4.unlinkSync(backupPath);
27
- fs4.renameSync(LOG_PATH, backupPath);
85
+ if (fs5.existsSync(backupPath)) fs5.unlinkSync(backupPath);
86
+ fs5.renameSync(LOG_PATH, backupPath);
28
87
  }
29
88
  } catch {
30
89
  }
@@ -42,7 +101,7 @@ function write(level, module, message, data) {
42
101
  if (data !== void 0) {
43
102
  entry.data = data instanceof Error ? data.message : String(data);
44
103
  }
45
- fs4.appendFileSync(LOG_PATH, JSON.stringify(entry) + "\n");
104
+ fs5.appendFileSync(LOG_PATH, JSON.stringify(entry) + "\n");
46
105
  } catch {
47
106
  }
48
107
  }
@@ -50,8 +109,8 @@ var LOG_DIR, LOG_PATH, MAX_LOG_SIZE, log;
50
109
  var init_logger = __esm({
51
110
  "src/logger.ts"() {
52
111
  "use strict";
53
- LOG_DIR = path4.join(os4.homedir(), ".aman-agent");
54
- LOG_PATH = path4.join(LOG_DIR, "debug.log");
112
+ LOG_DIR = path5.join(os4.homedir(), ".aman-agent");
113
+ LOG_PATH = path5.join(LOG_DIR, "debug.log");
55
114
  MAX_LOG_SIZE = 1048576;
56
115
  log = {
57
116
  debug: (module, message, data) => write("debug", module, message, data),
@@ -73,11 +132,11 @@ __export(user_model_exports, {
73
132
  predictBurnout: () => predictBurnout,
74
133
  saveUserModel: () => saveUserModel
75
134
  });
76
- import fs13 from "fs/promises";
77
- import path13 from "path";
135
+ import fs14 from "fs/promises";
136
+ import path14 from "path";
78
137
  import os12 from "os";
79
138
  function defaultModelPath() {
80
- return path13.join(os12.homedir(), ".acore", "user-model.json");
139
+ return path14.join(os12.homedir(), ".acore", "user-model.json");
81
140
  }
82
141
  function createEmptyModel() {
83
142
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -109,7 +168,7 @@ function emptyProfile() {
109
168
  async function loadUserModel(filePath) {
110
169
  const fp = filePath ?? defaultModelPath();
111
170
  try {
112
- const raw = await fs13.readFile(fp, "utf-8");
171
+ const raw = await fs14.readFile(fp, "utf-8");
113
172
  const parsed = JSON.parse(raw);
114
173
  if (parsed?.version !== 1) return null;
115
174
  return parsed;
@@ -119,11 +178,11 @@ async function loadUserModel(filePath) {
119
178
  }
120
179
  async function saveUserModel(model, filePath) {
121
180
  const fp = filePath ?? defaultModelPath();
122
- const dir = path13.dirname(fp);
123
- await fs13.mkdir(dir, { recursive: true });
181
+ const dir = path14.dirname(fp);
182
+ await fs14.mkdir(dir, { recursive: true });
124
183
  const tmp = fp + `.tmp-${Date.now()}`;
125
- await fs13.writeFile(tmp, JSON.stringify(model, null, 2), "utf-8");
126
- await fs13.rename(tmp, fp);
184
+ await fs14.writeFile(tmp, JSON.stringify(model, null, 2), "utf-8");
185
+ await fs14.rename(tmp, fp);
127
186
  }
128
187
  function aggregateSession(model, snapshot) {
129
188
  const sessions = [...model.sessions, snapshot];
@@ -386,21 +445,21 @@ var init_user_model = __esm({
386
445
  });
387
446
 
388
447
  // src/server/registry.ts
389
- import fs15 from "fs/promises";
390
- import path15 from "path";
448
+ import fs16 from "fs/promises";
449
+ import path16 from "path";
391
450
  import os14 from "os";
392
451
  function amanAgentHome() {
393
- return process.env.AMAN_AGENT_HOME || path15.join(os14.homedir(), ".aman-agent");
452
+ return process.env.AMAN_AGENT_HOME || path16.join(os14.homedir(), ".aman-agent");
394
453
  }
395
454
  function registryPath() {
396
- return path15.join(amanAgentHome(), "registry.json");
455
+ return path16.join(amanAgentHome(), "registry.json");
397
456
  }
398
457
  async function ensureHome() {
399
- await fs15.mkdir(amanAgentHome(), { recursive: true });
458
+ await fs16.mkdir(amanAgentHome(), { recursive: true });
400
459
  }
401
460
  async function readRaw() {
402
461
  try {
403
- const buf = await fs15.readFile(registryPath(), "utf-8");
462
+ const buf = await fs16.readFile(registryPath(), "utf-8");
404
463
  const parsed = JSON.parse(buf);
405
464
  return Array.isArray(parsed) ? parsed : [];
406
465
  } catch (err) {
@@ -414,10 +473,10 @@ async function readRaw() {
414
473
  async function writeAtomic(entries) {
415
474
  await ensureHome();
416
475
  const tmp = registryPath() + ".tmp";
417
- await fs15.writeFile(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
418
- await fs15.rename(tmp, registryPath());
476
+ await fs16.writeFile(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
477
+ await fs16.rename(tmp, registryPath());
419
478
  try {
420
- await fs15.chmod(registryPath(), 384);
479
+ await fs16.chmod(registryPath(), 384);
421
480
  } catch {
422
481
  }
423
482
  }
@@ -600,6 +659,473 @@ var init_delegate_remote = __esm({
600
659
  }
601
660
  });
602
661
 
662
+ // src/dev/stack-detector.ts
663
+ var stack_detector_exports = {};
664
+ __export(stack_detector_exports, {
665
+ scanStack: () => scanStack
666
+ });
667
+ import fs24 from "fs";
668
+ import path24 from "path";
669
+ function scanStack(projectPath) {
670
+ const languages = [];
671
+ const frameworks = [];
672
+ const databases = [];
673
+ const infra = [];
674
+ let isMonorepo = false;
675
+ let projectName = path24.basename(projectPath);
676
+ const goModPath = path24.join(projectPath, "go.mod");
677
+ if (fs24.existsSync(goModPath)) {
678
+ languages.push("go");
679
+ const content = fs24.readFileSync(goModPath, "utf-8");
680
+ const moduleMatch = content.match(/^module\s+(.+)$/m);
681
+ if (moduleMatch) {
682
+ const parts = moduleMatch[1].trim().split("/");
683
+ projectName = parts[parts.length - 1];
684
+ }
685
+ if (content.includes("gofiber/fiber")) frameworks.push("fiber");
686
+ if (content.includes("gin-gonic/gin")) frameworks.push("gin");
687
+ if (content.includes("go-chi/chi")) frameworks.push("chi");
688
+ if (content.includes("labstack/echo")) frameworks.push("echo");
689
+ }
690
+ const pkgPath = path24.join(projectPath, "package.json");
691
+ const hasTsConfig = fs24.existsSync(path24.join(projectPath, "tsconfig.json"));
692
+ if (fs24.existsSync(pkgPath)) {
693
+ try {
694
+ const pkg = JSON.parse(fs24.readFileSync(pkgPath, "utf-8"));
695
+ if (pkg.name) projectName = pkg.name;
696
+ if (hasTsConfig) {
697
+ languages.push("typescript");
698
+ } else {
699
+ languages.push("javascript");
700
+ }
701
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
702
+ for (const [dep, fwName] of Object.entries(FRAMEWORK_MAP)) {
703
+ if (allDeps?.[dep]) frameworks.push(fwName);
704
+ }
705
+ if (pkg.workspaces) isMonorepo = true;
706
+ } catch {
707
+ if (hasTsConfig) languages.push("typescript");
708
+ }
709
+ } else if (hasTsConfig) {
710
+ languages.push("typescript");
711
+ }
712
+ const cargoPath = path24.join(projectPath, "Cargo.toml");
713
+ if (fs24.existsSync(cargoPath)) {
714
+ languages.push("rust");
715
+ const content = fs24.readFileSync(cargoPath, "utf-8");
716
+ if (content.includes("[workspace]")) isMonorepo = true;
717
+ const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
718
+ if (nameMatch && !isMonorepo) projectName = nameMatch[1];
719
+ }
720
+ const pyprojectPath = path24.join(projectPath, "pyproject.toml");
721
+ if (fs24.existsSync(pyprojectPath)) {
722
+ languages.push("python");
723
+ const content = fs24.readFileSync(pyprojectPath, "utf-8");
724
+ if (content.includes("django")) frameworks.push("django");
725
+ if (content.includes("fastapi")) frameworks.push("fastapi");
726
+ if (content.includes("flask")) frameworks.push("flask");
727
+ }
728
+ if (fs24.existsSync(path24.join(projectPath, "pubspec.yaml"))) {
729
+ languages.push("dart");
730
+ frameworks.push("flutter");
731
+ }
732
+ if (fs24.existsSync(path24.join(projectPath, "Dockerfile"))) {
733
+ infra.push("docker");
734
+ }
735
+ const composeNames = ["docker-compose.yml", "docker-compose.yaml", "compose.yml", "compose.yaml"];
736
+ for (const name of composeNames) {
737
+ const composePath = path24.join(projectPath, name);
738
+ if (fs24.existsSync(composePath)) {
739
+ if (!infra.includes("docker")) infra.push("docker");
740
+ const content = fs24.readFileSync(composePath, "utf-8");
741
+ for (const [pattern, dbName] of Object.entries(DB_IMAGE_MAP)) {
742
+ if (content.includes(pattern) && !databases.includes(dbName)) {
743
+ databases.push(dbName);
744
+ }
745
+ }
746
+ break;
747
+ }
748
+ }
749
+ if (fs24.existsSync(path24.join(projectPath, ".github", "workflows"))) {
750
+ infra.push("github-actions");
751
+ }
752
+ for (const dir of ["k3s", "k8s", "deploy"]) {
753
+ if (fs24.existsSync(path24.join(projectPath, dir))) {
754
+ infra.push("kubernetes");
755
+ break;
756
+ }
757
+ }
758
+ if (fs24.existsSync(path24.join(projectPath, "Makefile"))) {
759
+ infra.push("make");
760
+ }
761
+ return {
762
+ projectName,
763
+ languages,
764
+ frameworks,
765
+ databases,
766
+ infra,
767
+ isMonorepo,
768
+ detectedAt: Date.now()
769
+ };
770
+ }
771
+ var FRAMEWORK_MAP, DB_IMAGE_MAP;
772
+ var init_stack_detector = __esm({
773
+ "src/dev/stack-detector.ts"() {
774
+ "use strict";
775
+ FRAMEWORK_MAP = {
776
+ next: "next",
777
+ react: "react",
778
+ remix: "remix",
779
+ express: "express",
780
+ fastify: "fastify",
781
+ hono: "hono",
782
+ "@nestjs/core": "nestjs",
783
+ vue: "vue",
784
+ svelte: "svelte",
785
+ nuxt: "nuxt"
786
+ };
787
+ DB_IMAGE_MAP = {
788
+ postgres: "postgresql",
789
+ mysql: "mysql",
790
+ mariadb: "mariadb",
791
+ mongo: "mongodb",
792
+ redis: "redis",
793
+ timescaledb: "timescaledb"
794
+ };
795
+ }
796
+ });
797
+
798
+ // src/dev/context-builder.ts
799
+ import path25 from "path";
800
+ import os22 from "os";
801
+ import { createDatabase as createDatabase2, recall as recall2 } from "@aman_asmuei/amem-core";
802
+ import {
803
+ getIdentity as acoreGetIdentity2
804
+ } from "@aman_asmuei/acore-core";
805
+ import {
806
+ listRuleCategories as arulesListCategories2
807
+ } from "@aman_asmuei/arules-core";
808
+ function trimToTokenBudget(items, maxTokens) {
809
+ const result = [];
810
+ let total = 0;
811
+ for (const item of items) {
812
+ const tokens = estimateTokens(item);
813
+ if (total + tokens > maxTokens) break;
814
+ result.push(item);
815
+ total += tokens;
816
+ }
817
+ return result;
818
+ }
819
+ async function buildContext2(stack, opts) {
820
+ const conventions = [];
821
+ const decisions = [];
822
+ const corrections = [];
823
+ const preferences = [];
824
+ const rules = [];
825
+ let memoriesUsed = 0;
826
+ try {
827
+ const amemDir = process.env.AMEM_DIR ?? path25.join(os22.homedir(), ".amem");
828
+ const dbPath = process.env.AMEM_DB ?? path25.join(amemDir, "memory.db");
829
+ const db2 = createDatabase2(dbPath);
830
+ const query = [stack.projectName, ...stack.languages, ...stack.frameworks].join(" ");
831
+ const result = await recall2(db2, { query, limit: 20 });
832
+ for (const mem of result.memories) {
833
+ switch (mem.type) {
834
+ case "pattern":
835
+ conventions.push(mem.content);
836
+ break;
837
+ case "decision":
838
+ decisions.push(mem.content);
839
+ break;
840
+ case "correction":
841
+ corrections.push(mem.content);
842
+ break;
843
+ case "preference":
844
+ preferences.push(mem.content);
845
+ break;
846
+ }
847
+ memoriesUsed++;
848
+ }
849
+ } catch {
850
+ }
851
+ try {
852
+ const identity = await acoreGetIdentity2(AGENT_SCOPE2);
853
+ if (identity?.content) {
854
+ const lines = identity.content.split("\n").filter(
855
+ (l) => l.startsWith("- ") && (l.toLowerCase().includes("prefer") || l.toLowerCase().includes("style") || l.toLowerCase().includes("convention"))
856
+ );
857
+ for (const line of lines) {
858
+ const text3 = line.replace(/^-\s*/, "").trim();
859
+ if (text3 && !preferences.includes(text3)) preferences.push(text3);
860
+ }
861
+ }
862
+ } catch {
863
+ }
864
+ try {
865
+ const categories = await arulesListCategories2(AGENT_SCOPE2);
866
+ for (const cat of categories) {
867
+ for (const ruleText of cat.rules) {
868
+ rules.push(ruleText);
869
+ }
870
+ }
871
+ } catch {
872
+ }
873
+ if (opts?.smart && opts.llmClient) {
874
+ try {
875
+ const client = opts.llmClient;
876
+ const rawData = [
877
+ `Project: ${stack.projectName}`,
878
+ `Stack: ${stack.languages.join(", ")} + ${stack.frameworks.join(", ")}`,
879
+ `Databases: ${stack.databases.join(", ") || "none detected"}`,
880
+ "",
881
+ conventions.length > 0 ? `Conventions:
882
+ ${conventions.map((c) => `- ${c}`).join("\n")}` : "",
883
+ decisions.length > 0 ? `Decisions:
884
+ ${decisions.map((d) => `- ${d}`).join("\n")}` : "",
885
+ corrections.length > 0 ? `Corrections:
886
+ ${corrections.map((c) => `- ${c}`).join("\n")}` : "",
887
+ preferences.length > 0 ? `Preferences:
888
+ ${preferences.map((p5) => `- ${p5}`).join("\n")}` : "",
889
+ rules.length > 0 ? `Rules:
890
+ ${rules.map((r) => `- ${r}`).join("\n")}` : ""
891
+ ].filter(Boolean).join("\n\n");
892
+ const response = await client.chat(
893
+ "You are a developer context assembler. Given raw developer history, output a merged, deduplicated set of conventions and decisions as markdown bullet lists. Group by: Conventions, Decisions, Corrections, Preferences, Rules. Be specific, not generic. Max 3000 tokens.",
894
+ [{ role: "user", content: rawData }],
895
+ () => {
896
+ }
897
+ );
898
+ const text3 = typeof response.message.content === "string" ? response.message.content : response.message.content.map((b) => b.text ?? "").join("");
899
+ const extractSection = (sectionName) => {
900
+ const regex = new RegExp(`##?\\s*${sectionName}[\\s\\S]*?(?=##|$)`, "i");
901
+ const match = text3.match(regex);
902
+ if (!match) return [];
903
+ return match[0].split("\n").filter((l) => l.startsWith("- ")).map((l) => l.replace(/^-\s*/, "").trim());
904
+ };
905
+ const smartConventions = extractSection("Conventions");
906
+ const smartDecisions = extractSection("Decisions");
907
+ const smartCorrections = extractSection("Corrections");
908
+ const smartPreferences = extractSection("Preferences");
909
+ const smartRules = extractSection("Rules");
910
+ return {
911
+ stack,
912
+ conventions: trimToTokenBudget(smartConventions.length > 0 ? smartConventions : conventions, TOKEN_LIMITS.conventions),
913
+ decisions: trimToTokenBudget(smartDecisions.length > 0 ? smartDecisions : decisions, TOKEN_LIMITS.decisions),
914
+ corrections: trimToTokenBudget(smartCorrections.length > 0 ? smartCorrections : corrections, TOKEN_LIMITS.corrections),
915
+ preferences: trimToTokenBudget(smartPreferences.length > 0 ? smartPreferences : preferences, TOKEN_LIMITS.preferences),
916
+ rules: trimToTokenBudget(smartRules.length > 0 ? smartRules : rules, TOKEN_LIMITS.rules),
917
+ metadata: {
918
+ generatedAt: Date.now(),
919
+ mode: "smart",
920
+ memoriesUsed
921
+ }
922
+ };
923
+ } catch {
924
+ }
925
+ }
926
+ return {
927
+ stack,
928
+ conventions: trimToTokenBudget(conventions, TOKEN_LIMITS.conventions),
929
+ decisions: trimToTokenBudget(decisions, TOKEN_LIMITS.decisions),
930
+ corrections: trimToTokenBudget(corrections, TOKEN_LIMITS.corrections),
931
+ preferences: trimToTokenBudget(preferences, TOKEN_LIMITS.preferences),
932
+ rules: trimToTokenBudget(rules, TOKEN_LIMITS.rules),
933
+ metadata: {
934
+ generatedAt: Date.now(),
935
+ mode: "template",
936
+ memoriesUsed
937
+ }
938
+ };
939
+ }
940
+ var AGENT_SCOPE2, TOKEN_LIMITS;
941
+ var init_context_builder = __esm({
942
+ "src/dev/context-builder.ts"() {
943
+ "use strict";
944
+ init_token_budget();
945
+ AGENT_SCOPE2 = process.env.AMAN_AGENT_SCOPE ?? "dev:agent";
946
+ TOKEN_LIMITS = {
947
+ conventions: 1500,
948
+ decisions: 1200,
949
+ corrections: 800,
950
+ preferences: 500,
951
+ rules: 800
952
+ };
953
+ }
954
+ });
955
+
956
+ // src/dev/claude-md-writer.ts
957
+ import fs25 from "fs";
958
+ import path26 from "path";
959
+ function formatStack(stack) {
960
+ const parts = [];
961
+ const goFrameworks = ["fiber", "gin", "chi", "echo"];
962
+ const jsFrameworks = ["next", "react", "remix", "express", "fastify", "hono", "nestjs", "vue", "svelte", "nuxt"];
963
+ const pyFrameworks = ["django", "fastapi", "flask"];
964
+ for (const lang of stack.languages) {
965
+ const fw = stack.frameworks.filter((f) => {
966
+ if (lang === "go" && goFrameworks.includes(f)) return true;
967
+ if ((lang === "typescript" || lang === "javascript") && jsFrameworks.includes(f)) return true;
968
+ if (lang === "python" && pyFrameworks.includes(f)) return true;
969
+ if (lang === "dart" && f === "flutter") return true;
970
+ return false;
971
+ });
972
+ const name = lang.charAt(0).toUpperCase() + lang.slice(1);
973
+ if (fw.length > 0) {
974
+ parts.push(`${name} (${fw.map((f) => f.charAt(0).toUpperCase() + f.slice(1)).join(", ")})`);
975
+ } else {
976
+ parts.push(name);
977
+ }
978
+ }
979
+ if (stack.databases.length > 0) {
980
+ parts.push(...stack.databases.map((d) => d.charAt(0).toUpperCase() + d.slice(1)));
981
+ }
982
+ return parts.join(" + ");
983
+ }
984
+ function renderToString(ctx) {
985
+ const lines = [];
986
+ const ts = new Date(ctx.metadata.generatedAt).toISOString();
987
+ lines.push(`# Project: ${ctx.stack.projectName}`);
988
+ lines.push(`<!-- aman-agent:dev generated=${ts} memories=${ctx.metadata.memoriesUsed} mode=${ctx.metadata.mode} -->`);
989
+ lines.push("");
990
+ const stackLine = formatStack(ctx.stack);
991
+ if (stackLine || ctx.stack.infra.length > 0) {
992
+ lines.push("## Stack");
993
+ if (stackLine) lines.push(`- ${stackLine}`);
994
+ if (ctx.stack.infra.length > 0) {
995
+ lines.push(`- Infra: ${ctx.stack.infra.join(", ")}`);
996
+ }
997
+ if (ctx.stack.isMonorepo) {
998
+ lines.push("- Monorepo");
999
+ }
1000
+ lines.push("");
1001
+ }
1002
+ if (ctx.conventions.length > 0) {
1003
+ lines.push("## Conventions");
1004
+ for (const c of ctx.conventions) lines.push(`- ${c}`);
1005
+ lines.push("");
1006
+ }
1007
+ if (ctx.decisions.length > 0) {
1008
+ lines.push("## Past Decisions");
1009
+ for (const d of ctx.decisions) lines.push(`- ${d}`);
1010
+ lines.push("");
1011
+ }
1012
+ if (ctx.corrections.length > 0) {
1013
+ lines.push("## Corrections");
1014
+ for (const c of ctx.corrections) lines.push(`- ${c}`);
1015
+ lines.push("");
1016
+ }
1017
+ if (ctx.preferences.length > 0) {
1018
+ lines.push("## Developer Preferences");
1019
+ for (const p5 of ctx.preferences) lines.push(`- ${p5}`);
1020
+ lines.push("");
1021
+ }
1022
+ if (ctx.rules.length > 0) {
1023
+ lines.push("## Rules");
1024
+ for (const r of ctx.rules) lines.push(`- ${r}`);
1025
+ lines.push("");
1026
+ }
1027
+ return lines.join("\n");
1028
+ }
1029
+ function parseMarker(content) {
1030
+ const match = content.match(
1031
+ /<!--\s*aman-agent:dev\s+generated=(\S+)\s+memories=(\d+)\s+mode=(\S+)\s*-->/
1032
+ );
1033
+ if (!match) return null;
1034
+ return {
1035
+ generatedAt: new Date(match[1]),
1036
+ memories: parseInt(match[2], 10),
1037
+ mode: match[3]
1038
+ };
1039
+ }
1040
+ function checkStaleness(projectPath) {
1041
+ const claudeMdPath = path26.join(projectPath, "CLAUDE.md");
1042
+ if (!fs25.existsSync(claudeMdPath)) {
1043
+ return { status: "missing" };
1044
+ }
1045
+ const content = fs25.readFileSync(claudeMdPath, "utf-8");
1046
+ const marker = parseMarker(content);
1047
+ if (!marker) {
1048
+ return { status: "no-marker" };
1049
+ }
1050
+ return { status: "fresh", generatedAt: marker.generatedAt };
1051
+ }
1052
+ function writeClaudeMd(ctx, projectPath) {
1053
+ const claudeMdPath = path26.join(projectPath, "CLAUDE.md");
1054
+ let backedUp = false;
1055
+ if (fs25.existsSync(claudeMdPath)) {
1056
+ const content = fs25.readFileSync(claudeMdPath, "utf-8");
1057
+ const marker = parseMarker(content);
1058
+ if (!marker) {
1059
+ fs25.copyFileSync(claudeMdPath, `${claudeMdPath}.bak`);
1060
+ backedUp = true;
1061
+ }
1062
+ }
1063
+ const md = renderToString(ctx);
1064
+ fs25.writeFileSync(claudeMdPath, md, "utf-8");
1065
+ return { written: true, backedUp, path: claudeMdPath };
1066
+ }
1067
+ var init_claude_md_writer = __esm({
1068
+ "src/dev/claude-md-writer.ts"() {
1069
+ "use strict";
1070
+ }
1071
+ });
1072
+
1073
+ // src/dev/dev-command.ts
1074
+ var dev_command_exports = {};
1075
+ __export(dev_command_exports, {
1076
+ runDev: () => runDev
1077
+ });
1078
+ import fs26 from "fs";
1079
+ import path27 from "path";
1080
+ function ensureGitignore(projectPath) {
1081
+ const gitignorePath = path27.join(projectPath, ".gitignore");
1082
+ if (!fs26.existsSync(gitignorePath)) return;
1083
+ const content = fs26.readFileSync(gitignorePath, "utf-8");
1084
+ if (content.includes("CLAUDE.md")) return;
1085
+ fs26.appendFileSync(gitignorePath, "\n# Generated by aman-agent dev\nCLAUDE.md\n");
1086
+ }
1087
+ async function runDev(projectPath, flags = {}, precomputedStack) {
1088
+ const resolved = path27.resolve(projectPath);
1089
+ if (!fs26.existsSync(resolved)) {
1090
+ return { success: false, generated: false, error: `Directory not found: ${resolved}` };
1091
+ }
1092
+ const stack = precomputedStack ?? scanStack(resolved);
1093
+ if (flags.diff) {
1094
+ const ctx2 = await buildContext2(stack, { smart: flags.smart });
1095
+ const newContent = renderToString(ctx2);
1096
+ const existingPath = path27.join(resolved, "CLAUDE.md");
1097
+ const existing = fs26.existsSync(existingPath) ? fs26.readFileSync(existingPath, "utf-8") : "";
1098
+ return {
1099
+ success: true,
1100
+ generated: false,
1101
+ diff: existing === newContent ? "(no changes)" : newContent,
1102
+ context: ctx2
1103
+ };
1104
+ }
1105
+ if (!flags.force) {
1106
+ const staleness = checkStaleness(resolved);
1107
+ if (staleness.status === "fresh") {
1108
+ return { success: true, generated: false, skippedReason: "fresh" };
1109
+ }
1110
+ }
1111
+ const ctx = await buildContext2(stack, { smart: flags.smart });
1112
+ const writeResult = writeClaudeMd(ctx, resolved);
1113
+ ensureGitignore(resolved);
1114
+ return {
1115
+ success: true,
1116
+ generated: writeResult.written,
1117
+ context: ctx
1118
+ };
1119
+ }
1120
+ var init_dev_command = __esm({
1121
+ "src/dev/dev-command.ts"() {
1122
+ "use strict";
1123
+ init_stack_detector();
1124
+ init_context_builder();
1125
+ init_claude_md_writer();
1126
+ }
1127
+ });
1128
+
603
1129
  // src/index.ts
604
1130
  import { Command } from "commander";
605
1131
  import * as p4 from "@clack/prompts";
@@ -620,8 +1146,26 @@ var DEFAULT_HOOKS = {
620
1146
  featureHints: true,
621
1147
  personalityAdapt: true
622
1148
  };
1149
+ function homeDir() {
1150
+ return process.env.AMAN_HOME || process.env.AMAN_AGENT_HOME || path.join(os.homedir(), ".aman-agent");
1151
+ }
1152
+ function identityDir() {
1153
+ return path.join(homeDir(), "identity");
1154
+ }
1155
+ function rulesDir() {
1156
+ return path.join(homeDir(), "rules");
1157
+ }
1158
+ function memoryDir() {
1159
+ return path.join(homeDir(), "memory");
1160
+ }
1161
+ function workflowsDir() {
1162
+ return path.join(homeDir(), "workflows");
1163
+ }
1164
+ function skillsDir() {
1165
+ return path.join(homeDir(), "skills");
1166
+ }
623
1167
  function configDir() {
624
- return process.env.AMAN_AGENT_HOME || path.join(os.homedir(), ".aman-agent");
1168
+ return homeDir();
625
1169
  }
626
1170
  function configPath() {
627
1171
  return path.join(configDir(), "config.json");
@@ -646,76 +1190,54 @@ function saveConfig(config) {
646
1190
  );
647
1191
  }
648
1192
 
649
- // src/prompt.ts
650
- import fs3 from "fs";
651
- import path3 from "path";
652
- import os3 from "os";
653
-
654
- // src/token-budget.ts
655
- function estimateTokens(text3) {
656
- return Math.round(text3.split(/\s+/).filter(Boolean).length * 1.3);
657
- }
658
- var PRIORITIES = [
659
- "identity",
660
- // core.md — always include
661
- "user",
662
- // user.md — user profile, always include
663
- "guardrails",
664
- // rules.md — safety critical
665
- "workflows",
666
- // flow.md — behavioral
667
- "tools",
668
- // kit.md — capabilities
669
- "skills"
670
- // skills.md — can be truncated
1193
+ // src/migrate.ts
1194
+ import fs2 from "fs";
1195
+ import path2 from "path";
1196
+ import os2 from "os";
1197
+ var MIGRATION_MAP = [
1198
+ { oldName: ".acore", newSubdir: "identity" },
1199
+ { oldName: ".arules", newSubdir: "rules" },
1200
+ { oldName: ".aflow", newSubdir: "workflows" },
1201
+ { oldName: ".askill", newSubdir: "skills" },
1202
+ { oldName: ".amem", newSubdir: "memory" },
1203
+ { oldName: ".aeval", newSubdir: "eval" }
671
1204
  ];
672
- function buildBudgetedPrompt(components, maxTokens = 8e3) {
673
- const included = [];
674
- const truncated = [];
675
- const parts = [];
676
- let totalTokens = 0;
677
- const sorted = [...components].sort((a, b) => {
678
- const aPri = PRIORITIES.indexOf(a.name);
679
- const bPri = PRIORITIES.indexOf(b.name);
680
- return (aPri === -1 ? 99 : aPri) - (bPri === -1 ? 99 : bPri);
681
- });
682
- for (const comp of sorted) {
683
- if (totalTokens + comp.tokens <= maxTokens) {
684
- parts.push(comp.content);
685
- included.push(comp.name);
686
- totalTokens += comp.tokens;
687
- } else {
688
- const halfContent = comp.content.slice(0, Math.floor(comp.content.length / 2));
689
- const halfTokens = estimateTokens(halfContent);
690
- if (totalTokens + halfTokens <= maxTokens) {
691
- parts.push(halfContent + "\n\n[... truncated for context budget ...]");
692
- included.push(comp.name + " (partial)");
693
- totalTokens += halfTokens;
694
- } else {
695
- truncated.push(comp.name);
696
- }
1205
+ function migrateIfNeeded() {
1206
+ const home2 = os2.homedir();
1207
+ const target = homeDir();
1208
+ const migrated = [];
1209
+ for (const { oldName, newSubdir } of MIGRATION_MAP) {
1210
+ const oldDir = path2.join(home2, oldName);
1211
+ const newDir = path2.join(target, newSubdir);
1212
+ if (!fs2.existsSync(oldDir)) continue;
1213
+ if (fs2.existsSync(newDir) && fs2.readdirSync(newDir).length > 0) continue;
1214
+ fs2.mkdirSync(newDir, { recursive: true });
1215
+ for (const entry of fs2.readdirSync(oldDir)) {
1216
+ fs2.renameSync(path2.join(oldDir, entry), path2.join(newDir, entry));
697
1217
  }
1218
+ fs2.rmSync(oldDir, { recursive: true, force: true });
1219
+ migrated.push(newSubdir);
698
1220
  }
699
- return {
700
- prompt: parts.join("\n\n---\n\n"),
701
- included,
702
- truncated,
703
- totalTokens
704
- };
1221
+ return { migrated };
705
1222
  }
706
1223
 
1224
+ // src/prompt.ts
1225
+ init_token_budget();
1226
+ import fs4 from "fs";
1227
+ import path4 from "path";
1228
+ import os3 from "os";
1229
+
707
1230
  // src/user-identity.ts
708
- import fs2 from "fs";
709
- import path2 from "path";
710
- import os2 from "os";
711
- var USER_FILE = path2.join(os2.homedir(), ".acore", "user.md");
1231
+ import fs3 from "fs";
1232
+ import path3 from "path";
1233
+ var USER_FILE = path3.join(identityDir(), "user.md");
712
1234
  function hasUserIdentity() {
713
- return fs2.existsSync(USER_FILE);
1235
+ return fs3.existsSync(USER_FILE);
714
1236
  }
715
1237
  function loadUserIdentity() {
716
- if (!fs2.existsSync(USER_FILE)) return null;
1238
+ if (!fs3.existsSync(USER_FILE)) return null;
717
1239
  try {
718
- const content = fs2.readFileSync(USER_FILE, "utf-8");
1240
+ const content = fs3.readFileSync(USER_FILE, "utf-8");
719
1241
  const get = (key) => {
720
1242
  const match = content.match(new RegExp(`^- ${key}:\\s*(.+)$`, "m"));
721
1243
  return match?.[1]?.trim() ?? "";
@@ -746,8 +1268,8 @@ function loadUserIdentity() {
746
1268
  }
747
1269
  }
748
1270
  function saveUserIdentity(user) {
749
- const dir = path2.dirname(USER_FILE);
750
- if (!fs2.existsSync(dir)) fs2.mkdirSync(dir, { recursive: true });
1271
+ const dir = path3.dirname(USER_FILE);
1272
+ if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
751
1273
  const lines = [
752
1274
  "# User Profile",
753
1275
  "",
@@ -772,7 +1294,7 @@ function saveUserIdentity(user) {
772
1294
  `- Created: ${user.createdAt}`,
773
1295
  `- Updated: ${user.updatedAt}`
774
1296
  );
775
- fs2.writeFileSync(USER_FILE, lines.join("\n") + "\n", "utf-8");
1297
+ fs3.writeFileSync(USER_FILE, lines.join("\n") + "\n", "utf-8");
776
1298
  }
777
1299
  function formatUserContext(user) {
778
1300
  const parts = [
@@ -834,19 +1356,19 @@ var ECOSYSTEM_FILES = [
834
1356
  ];
835
1357
  function resolveLayerPath(entry, home2, profile) {
836
1358
  if (profile && entry.profileOverridable) {
837
- const profilePath = path3.join(home2, ".acore", "profiles", profile, entry.file);
838
- if (fs3.existsSync(profilePath)) return profilePath;
1359
+ const profilePath = path4.join(home2, ".acore", "profiles", profile, entry.file);
1360
+ if (fs4.existsSync(profilePath)) return profilePath;
839
1361
  if (entry.name === "guardrails") {
840
- const altPath = path3.join(home2, ".acore", "profiles", profile, "rules.md");
841
- if (fs3.existsSync(altPath)) return altPath;
1362
+ const altPath = path4.join(home2, ".acore", "profiles", profile, "rules.md");
1363
+ if (fs4.existsSync(altPath)) return altPath;
842
1364
  }
843
1365
  if (entry.name === "skills") {
844
- const altPath = path3.join(home2, ".acore", "profiles", profile, "skills.md");
845
- if (fs3.existsSync(altPath)) return altPath;
1366
+ const altPath = path4.join(home2, ".acore", "profiles", profile, "skills.md");
1367
+ if (fs4.existsSync(altPath)) return altPath;
846
1368
  }
847
1369
  }
848
- const globalPath = path3.join(home2, entry.dir, entry.file);
849
- if (fs3.existsSync(globalPath)) return globalPath;
1370
+ const globalPath = path4.join(home2, entry.dir, entry.file);
1371
+ if (fs4.existsSync(globalPath)) return globalPath;
850
1372
  return null;
851
1373
  }
852
1374
  function assembleSystemPrompt(maxTokens, profile) {
@@ -855,7 +1377,7 @@ function assembleSystemPrompt(maxTokens, profile) {
855
1377
  for (const entry of ECOSYSTEM_FILES) {
856
1378
  const filePath = resolveLayerPath(entry, home2, profile);
857
1379
  if (filePath) {
858
- const content = fs3.readFileSync(filePath, "utf-8").trim();
1380
+ const content = fs4.readFileSync(filePath, "utf-8").trim();
859
1381
  components.push({
860
1382
  name: entry.name,
861
1383
  content,
@@ -863,9 +1385,9 @@ function assembleSystemPrompt(maxTokens, profile) {
863
1385
  });
864
1386
  }
865
1387
  }
866
- const contextPath = path3.join(process.cwd(), ".acore", "context.md");
867
- if (fs3.existsSync(contextPath)) {
868
- const content = fs3.readFileSync(contextPath, "utf-8").trim();
1388
+ const contextPath = path4.join(process.cwd(), ".acore", "context.md");
1389
+ if (fs4.existsSync(contextPath)) {
1390
+ const content = fs4.readFileSync(contextPath, "utf-8").trim();
869
1391
  components.push({
870
1392
  name: "context",
871
1393
  content,
@@ -891,14 +1413,14 @@ function assembleSystemPrompt(maxTokens, profile) {
891
1413
  };
892
1414
  }
893
1415
  function listProfiles() {
894
- const profilesDir = path3.join(os3.homedir(), ".acore", "profiles");
895
- if (!fs3.existsSync(profilesDir)) return [];
1416
+ const profilesDir = path4.join(os3.homedir(), ".acore", "profiles");
1417
+ if (!fs4.existsSync(profilesDir)) return [];
896
1418
  const profiles = [];
897
- for (const entry of fs3.readdirSync(profilesDir, { withFileTypes: true })) {
1419
+ for (const entry of fs4.readdirSync(profilesDir, { withFileTypes: true })) {
898
1420
  if (!entry.isDirectory()) continue;
899
- const corePath = path3.join(profilesDir, entry.name, "core.md");
900
- if (!fs3.existsSync(corePath)) continue;
901
- const content = fs3.readFileSync(corePath, "utf-8");
1421
+ const corePath = path4.join(profilesDir, entry.name, "core.md");
1422
+ if (!fs4.existsSync(corePath)) continue;
1423
+ const content = fs4.readFileSync(corePath, "utf-8");
902
1424
  const nameMatch = content.match(/^# (.+)/m);
903
1425
  const personalityMatch = content.match(/- Personality:\s*(.+)/);
904
1426
  profiles.push({
@@ -913,13 +1435,13 @@ function getProfileAiName(profile) {
913
1435
  const home2 = os3.homedir();
914
1436
  let corePath;
915
1437
  if (profile) {
916
- const profileCorePath = path3.join(home2, ".acore", "profiles", profile, "core.md");
917
- corePath = fs3.existsSync(profileCorePath) ? profileCorePath : path3.join(home2, ".acore", "core.md");
1438
+ const profileCorePath = path4.join(home2, ".acore", "profiles", profile, "core.md");
1439
+ corePath = fs4.existsSync(profileCorePath) ? profileCorePath : path4.join(home2, ".acore", "core.md");
918
1440
  } else {
919
- corePath = path3.join(home2, ".acore", "core.md");
1441
+ corePath = path4.join(home2, ".acore", "core.md");
920
1442
  }
921
- if (!fs3.existsSync(corePath)) return "Assistant";
922
- const content = fs3.readFileSync(corePath, "utf-8");
1443
+ if (!fs4.existsSync(corePath)) return "Assistant";
1444
+ const content = fs4.readFileSync(corePath, "utf-8");
923
1445
  const match = content.match(/^# (.+)$/m);
924
1446
  return match?.[1]?.trim() || "Assistant";
925
1447
  }
@@ -1976,8 +2498,8 @@ var McpManager = class {
1976
2498
 
1977
2499
  // src/agent.ts
1978
2500
  import * as readline from "readline";
1979
- import fs22 from "fs";
1980
- import path22 from "path";
2501
+ import fs23 from "fs";
2502
+ import path23 from "path";
1981
2503
  import os21 from "os";
1982
2504
  import pc7 from "picocolors";
1983
2505
  import { marked } from "marked";
@@ -1985,15 +2507,15 @@ import { markedTerminal } from "marked-terminal";
1985
2507
  import logUpdate from "log-update";
1986
2508
 
1987
2509
  // src/commands.ts
1988
- import fs19 from "fs";
1989
- import path19 from "path";
2510
+ import fs20 from "fs";
2511
+ import path20 from "path";
1990
2512
  import os18 from "os";
1991
2513
  import { execFileSync as execFileSync3 } from "child_process";
1992
2514
  import pc6 from "picocolors";
1993
2515
 
1994
2516
  // src/layers/parsers.ts
1995
- import fs5 from "fs";
1996
- import path5 from "path";
2517
+ import fs6 from "fs";
2518
+ import path6 from "path";
1997
2519
  import os5 from "os";
1998
2520
  var home = os5.homedir();
1999
2521
  var LAYER_FILES = [
@@ -2031,11 +2553,11 @@ function getLayerSummary(name, content) {
2031
2553
  }
2032
2554
  function getEcosystemStatus(mcpToolCount, amemConnected) {
2033
2555
  const layers = LAYER_FILES.map((entry) => {
2034
- const filePath = path5.join(home, entry.dir, entry.file);
2035
- const exists = fs5.existsSync(filePath);
2556
+ const filePath = path6.join(home, entry.dir, entry.file);
2557
+ const exists = fs6.existsSync(filePath);
2036
2558
  let summary = "not configured";
2037
2559
  if (exists) {
2038
- const content = fs5.readFileSync(filePath, "utf-8");
2560
+ const content = fs6.readFileSync(filePath, "utf-8");
2039
2561
  summary = getLayerSummary(entry.name, content);
2040
2562
  }
2041
2563
  return { name: entry.name, exists, path: filePath, summary };
@@ -2073,25 +2595,25 @@ import {
2073
2595
  importFromTeam,
2074
2596
  syncToCopilot
2075
2597
  } from "@aman_asmuei/amem-core";
2076
- import path6 from "path";
2598
+ import path7 from "path";
2077
2599
  import os6 from "os";
2078
- import fs6 from "fs";
2600
+ import fs7 from "fs";
2079
2601
  var db = null;
2080
2602
  var currentProject = "global";
2081
2603
  async function initMemory(project) {
2082
2604
  if (db) return db;
2083
- const amemDir = process.env.AMEM_DIR ?? path6.join(os6.homedir(), ".amem");
2084
- if (!fs6.existsSync(amemDir)) fs6.mkdirSync(amemDir, { recursive: true });
2085
- const dbPath = process.env.AMEM_DB ?? path6.join(amemDir, "memory.db");
2605
+ const amemDir = process.env.AMEM_DIR ?? path7.join(os6.homedir(), ".amem");
2606
+ if (!fs7.existsSync(amemDir)) fs7.mkdirSync(amemDir, { recursive: true });
2607
+ const dbPath = process.env.AMEM_DB ?? path7.join(amemDir, "memory.db");
2086
2608
  try {
2087
2609
  db = createDatabase(dbPath);
2088
2610
  } catch (err) {
2089
2611
  const backupPath = `${dbPath}.corrupt.${Date.now()}`;
2090
2612
  try {
2091
- if (fs6.existsSync(dbPath)) {
2092
- fs6.renameSync(dbPath, backupPath);
2093
- if (fs6.existsSync(`${dbPath}-wal`)) fs6.unlinkSync(`${dbPath}-wal`);
2094
- if (fs6.existsSync(`${dbPath}-shm`)) fs6.unlinkSync(`${dbPath}-shm`);
2613
+ if (fs7.existsSync(dbPath)) {
2614
+ fs7.renameSync(dbPath, backupPath);
2615
+ if (fs7.existsSync(`${dbPath}-wal`)) fs7.unlinkSync(`${dbPath}-wal`);
2616
+ if (fs7.existsSync(`${dbPath}-shm`)) fs7.unlinkSync(`${dbPath}-shm`);
2095
2617
  console.error(`[amem] Database corrupted \u2014 backed up to ${backupPath}`);
2096
2618
  console.error("[amem] Creating fresh database. Previous memories are in the backup file.");
2097
2619
  db = createDatabase(dbPath);
@@ -2240,7 +2762,7 @@ async function memoryRepair(opts = {}) {
2240
2762
  actions: diag.issues.map((issue) => `Would fix: ${issue.suggestion}`)
2241
2763
  };
2242
2764
  }
2243
- const dbPath = process.env.AMEM_DB ?? path6.join(os6.homedir(), ".amem", "memory.db");
2765
+ const dbPath = process.env.AMEM_DB ?? path7.join(os6.homedir(), ".amem", "memory.db");
2244
2766
  const result = repairDatabase(dbPath);
2245
2767
  return {
2246
2768
  dryRun: false,
@@ -2336,8 +2858,8 @@ async function memorySync(action, opts = {}) {
2336
2858
  }
2337
2859
 
2338
2860
  // src/profile-templates.ts
2339
- import fs7 from "fs";
2340
- import path7 from "path";
2861
+ import fs8 from "fs";
2862
+ import path8 from "path";
2341
2863
  import os7 from "os";
2342
2864
  var BUILT_IN_PROFILES = [
2343
2865
  {
@@ -2431,9 +2953,9 @@ var BUILT_IN_PROFILES = [
2431
2953
  function installProfileTemplate(templateName, userName) {
2432
2954
  const template = BUILT_IN_PROFILES.find((t) => t.name === templateName);
2433
2955
  if (!template) return null;
2434
- const profileDir = path7.join(os7.homedir(), ".acore", "profiles", template.name);
2435
- if (fs7.existsSync(profileDir)) return `Profile already exists: ${template.name}`;
2436
- fs7.mkdirSync(profileDir, { recursive: true });
2956
+ const profileDir = path8.join(os7.homedir(), ".acore", "profiles", template.name);
2957
+ if (fs8.existsSync(profileDir)) return `Profile already exists: ${template.name}`;
2958
+ fs8.mkdirSync(profileDir, { recursive: true });
2437
2959
  let core = template.core;
2438
2960
  if (userName) {
2439
2961
  core += `
@@ -2447,12 +2969,12 @@ function installProfileTemplate(templateName, userName) {
2447
2969
  - Detail level: balanced
2448
2970
  `;
2449
2971
  }
2450
- fs7.writeFileSync(path7.join(profileDir, "core.md"), core, "utf-8");
2972
+ fs8.writeFileSync(path8.join(profileDir, "core.md"), core, "utf-8");
2451
2973
  if (template.rules) {
2452
- fs7.writeFileSync(path7.join(profileDir, "rules.md"), template.rules, "utf-8");
2974
+ fs8.writeFileSync(path8.join(profileDir, "rules.md"), template.rules, "utf-8");
2453
2975
  }
2454
2976
  if (template.skills) {
2455
- fs7.writeFileSync(path7.join(profileDir, "skills.md"), template.skills, "utf-8");
2977
+ fs8.writeFileSync(path8.join(profileDir, "skills.md"), template.skills, "utf-8");
2456
2978
  }
2457
2979
  return null;
2458
2980
  }
@@ -2463,21 +2985,21 @@ import pc from "picocolors";
2463
2985
 
2464
2986
  // src/showcase-bridge.ts
2465
2987
  init_logger();
2466
- import fs8 from "fs";
2467
- import path8 from "path";
2988
+ import fs9 from "fs";
2989
+ import path9 from "path";
2468
2990
  import os8 from "os";
2469
2991
  var cachedManifest = null;
2470
2992
  var cachedShowcaseRoot = null;
2471
2993
  function findShowcaseRoot() {
2472
2994
  const candidates = [
2473
2995
  // Sibling in monorepo
2474
- path8.join(os8.homedir(), "project-aman", "aman-showcase"),
2475
- path8.join(process.cwd(), "..", "aman-showcase"),
2996
+ path9.join(os8.homedir(), "project-aman", "aman-showcase"),
2997
+ path9.join(process.cwd(), "..", "aman-showcase"),
2476
2998
  // npm global install
2477
- path8.join(process.cwd(), "node_modules", "@aman_asmuei", "aman-showcase")
2999
+ path9.join(process.cwd(), "node_modules", "@aman_asmuei", "aman-showcase")
2478
3000
  ];
2479
3001
  for (const candidate of candidates) {
2480
- if (fs8.existsSync(path8.join(candidate, "src", "manifest.ts")) || fs8.existsSync(path8.join(candidate, "dist", "index.js"))) {
3002
+ if (fs9.existsSync(path9.join(candidate, "src", "manifest.ts")) || fs9.existsSync(path9.join(candidate, "dist", "index.js"))) {
2481
3003
  return candidate;
2482
3004
  }
2483
3005
  }
@@ -2507,10 +3029,10 @@ function loadShowcaseManifest() {
2507
3029
  return cachedManifest;
2508
3030
  }
2509
3031
  cachedShowcaseRoot = root;
2510
- const manifestSrc = path8.join(root, "src", "manifest.ts");
2511
- if (fs8.existsSync(manifestSrc)) {
3032
+ const manifestSrc = path9.join(root, "src", "manifest.ts");
3033
+ if (fs9.existsSync(manifestSrc)) {
2512
3034
  try {
2513
- const content = fs8.readFileSync(manifestSrc, "utf-8");
3035
+ const content = fs9.readFileSync(manifestSrc, "utf-8");
2514
3036
  const parsed = parseManifestSource(content);
2515
3037
  if (parsed.length > 0) {
2516
3038
  cachedManifest = parsed;
@@ -2521,7 +3043,7 @@ function loadShowcaseManifest() {
2521
3043
  }
2522
3044
  }
2523
3045
  try {
2524
- const dirs = fs8.readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".") && !["node_modules", "dist", "src", "bin", "docs"].includes(d.name)).filter((d) => fs8.existsSync(path8.join(root, d.name, "identity")));
3046
+ 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
3047
  cachedManifest = dirs.map((d) => ({
2526
3048
  name: d.name,
2527
3049
  title: d.name.charAt(0).toUpperCase() + d.name.slice(1),
@@ -2540,69 +3062,69 @@ function installShowcaseTemplate(name) {
2540
3062
  if (!root) {
2541
3063
  throw new Error("aman-showcase package not found. Install it or check the path.");
2542
3064
  }
2543
- const showcaseDir = path8.join(root, name);
2544
- if (!fs8.existsSync(showcaseDir) || !fs8.existsSync(path8.join(showcaseDir, "identity"))) {
3065
+ const showcaseDir = path9.join(root, name);
3066
+ if (!fs9.existsSync(showcaseDir) || !fs9.existsSync(path9.join(showcaseDir, "identity"))) {
2545
3067
  throw new Error(`Showcase "${name}" not found in ${root}`);
2546
3068
  }
2547
3069
  const result = { installed: [], backed_up: [], env_example: "" };
2548
3070
  const home2 = os8.homedir();
2549
3071
  const copies = [
2550
3072
  {
2551
- src: path8.join(showcaseDir, "identity", "core.md"),
2552
- dest: path8.join(home2, ".acore", "core.md"),
3073
+ src: path9.join(showcaseDir, "identity", "core.md"),
3074
+ dest: path9.join(home2, ".acore", "core.md"),
2553
3075
  label: "~/.acore/core.md (identity)"
2554
3076
  },
2555
3077
  {
2556
- src: path8.join(showcaseDir, "workflows", "flow.md"),
2557
- dest: path8.join(home2, ".aflow", "flow.md"),
3078
+ src: path9.join(showcaseDir, "workflows", "flow.md"),
3079
+ dest: path9.join(home2, ".aflow", "flow.md"),
2558
3080
  label: "~/.aflow/flow.md (workflows)"
2559
3081
  },
2560
3082
  {
2561
- src: path8.join(showcaseDir, "rules", "rules.md"),
2562
- dest: path8.join(home2, ".arules", "rules.md"),
3083
+ src: path9.join(showcaseDir, "rules", "rules.md"),
3084
+ dest: path9.join(home2, ".arules", "rules.md"),
2563
3085
  label: "~/.arules/rules.md (guardrails)"
2564
3086
  }
2565
3087
  ];
2566
- const skillsSrc = path8.join(showcaseDir, "skills");
2567
- if (fs8.existsSync(skillsSrc)) {
2568
- const skillFiles = fs8.readdirSync(skillsSrc).filter((f) => f.endsWith(".md"));
3088
+ const skillsSrc = path9.join(showcaseDir, "skills");
3089
+ if (fs9.existsSync(skillsSrc)) {
3090
+ const skillFiles = fs9.readdirSync(skillsSrc).filter((f) => f.endsWith(".md"));
2569
3091
  if (skillFiles.length > 0) {
2570
3092
  const skillParts = [];
2571
3093
  for (const skillFile of skillFiles) {
2572
- const content = fs8.readFileSync(path8.join(skillsSrc, skillFile), "utf-8").trim();
3094
+ const content = fs9.readFileSync(path9.join(skillsSrc, skillFile), "utf-8").trim();
2573
3095
  if (content) skillParts.push(content);
2574
3096
  }
2575
3097
  if (skillParts.length > 0) {
2576
- const skillsDest = path8.join(home2, ".askill", "skills.md");
3098
+ const skillsDest = path9.join(home2, ".askill", "skills.md");
2577
3099
  const consolidated = `# Skills
2578
3100
 
2579
3101
  ${skillParts.join("\n\n---\n\n")}
2580
3102
  `;
2581
- if (fs8.existsSync(skillsDest)) {
2582
- fs8.copyFileSync(skillsDest, `${skillsDest}.bak`);
3103
+ if (fs9.existsSync(skillsDest)) {
3104
+ fs9.copyFileSync(skillsDest, `${skillsDest}.bak`);
2583
3105
  result.backed_up.push("~/.askill/skills.md (skills)");
2584
3106
  }
2585
- fs8.mkdirSync(path8.dirname(skillsDest), { recursive: true });
2586
- fs8.writeFileSync(skillsDest, consolidated, "utf-8");
3107
+ fs9.mkdirSync(path9.dirname(skillsDest), { recursive: true });
3108
+ fs9.writeFileSync(skillsDest, consolidated, "utf-8");
2587
3109
  result.installed.push(`~/.askill/skills.md (${skillFiles.length} skill${skillFiles.length > 1 ? "s" : ""} consolidated)`);
2588
3110
  }
2589
3111
  }
2590
3112
  }
2591
3113
  for (const { src, dest, label } of copies) {
2592
- if (!fs8.existsSync(src)) continue;
2593
- if (fs8.existsSync(dest)) {
3114
+ if (!fs9.existsSync(src)) continue;
3115
+ if (fs9.existsSync(dest)) {
2594
3116
  const backup = `${dest}.bak`;
2595
- fs8.copyFileSync(dest, backup);
3117
+ fs9.copyFileSync(dest, backup);
2596
3118
  result.backed_up.push(label);
2597
3119
  }
2598
- fs8.mkdirSync(path8.dirname(dest), { recursive: true });
2599
- fs8.copyFileSync(src, dest);
3120
+ fs9.mkdirSync(path9.dirname(dest), { recursive: true });
3121
+ fs9.copyFileSync(src, dest);
2600
3122
  result.installed.push(label);
2601
3123
  }
2602
- const envExample = path8.join(showcaseDir, "config", "telegram.env.example");
2603
- if (fs8.existsSync(envExample)) {
2604
- const destEnv = path8.join(process.cwd(), ".env.example");
2605
- fs8.copyFileSync(envExample, destEnv);
3124
+ const envExample = path9.join(showcaseDir, "config", "telegram.env.example");
3125
+ if (fs9.existsSync(envExample)) {
3126
+ const destEnv = path9.join(process.cwd(), ".env.example");
3127
+ fs9.copyFileSync(envExample, destEnv);
2606
3128
  result.env_example = destEnv;
2607
3129
  }
2608
3130
  log.debug("showcase", `Installed showcase: ${name} (${result.installed.length} files)`);
@@ -2862,31 +3384,31 @@ async function editProfile(current) {
2862
3384
  }
2863
3385
 
2864
3386
  // src/files.ts
2865
- import fs9 from "fs";
2866
- import path9 from "path";
3387
+ import fs10 from "fs";
3388
+ import path10 from "path";
2867
3389
  import os9 from "os";
2868
3390
  var MAX_READ_BYTES = 5e4;
2869
- var HOME = fs9.realpathSync(os9.homedir());
2870
- var TMPDIR = fs9.realpathSync(os9.tmpdir());
2871
- var CWD = fs9.realpathSync(process.cwd());
3391
+ var HOME = fs10.realpathSync(os9.homedir());
3392
+ var TMPDIR = fs10.realpathSync(os9.tmpdir());
3393
+ var CWD = fs10.realpathSync(process.cwd());
2872
3394
  function realOrBest(p5) {
2873
- const parts = p5.split(path9.sep);
3395
+ const parts = p5.split(path10.sep);
2874
3396
  for (let i = parts.length; i > 0; i--) {
2875
- const candidate = parts.slice(0, i).join(path9.sep) || path9.sep;
3397
+ const candidate = parts.slice(0, i).join(path10.sep) || path10.sep;
2876
3398
  try {
2877
- const real = fs9.realpathSync(candidate);
2878
- const remainder = parts.slice(i).join(path9.sep);
2879
- return remainder ? `${real}${path9.sep}${remainder}` : real;
3399
+ const real = fs10.realpathSync(candidate);
3400
+ const remainder = parts.slice(i).join(path10.sep);
3401
+ return remainder ? `${real}${path10.sep}${remainder}` : real;
2880
3402
  } catch {
2881
3403
  }
2882
3404
  }
2883
3405
  return p5;
2884
3406
  }
2885
3407
  function isUnderDir(real, dir) {
2886
- return real === dir || real.startsWith(dir + path9.sep);
3408
+ return real === dir || real.startsWith(dir + path10.sep);
2887
3409
  }
2888
3410
  function assertSafePath(filePath) {
2889
- const resolved = path9.resolve(filePath);
3411
+ const resolved = path10.resolve(filePath);
2890
3412
  const real = realOrBest(resolved);
2891
3413
  if (!isUnderDir(real, HOME) && !isUnderDir(real, CWD) && !isUnderDir(real, TMPDIR)) {
2892
3414
  throw new Error(`Path is outside allowed directories (home or cwd): ${real}`);
@@ -2895,20 +3417,20 @@ function assertSafePath(filePath) {
2895
3417
  }
2896
3418
  async function readFile(filePath) {
2897
3419
  const resolved = assertSafePath(filePath);
2898
- if (!fs9.existsSync(resolved)) {
3420
+ if (!fs10.existsSync(resolved)) {
2899
3421
  throw new Error(`File not found: ${resolved}`);
2900
3422
  }
2901
- const stat = fs9.statSync(resolved);
3423
+ const stat = fs10.statSync(resolved);
2902
3424
  if (stat.isDirectory()) {
2903
3425
  throw new Error(`Path is a directory, not a file: ${resolved}. Use /file list instead.`);
2904
3426
  }
2905
3427
  const size = stat.size;
2906
3428
  const buf = Buffer.alloc(Math.min(size, MAX_READ_BYTES));
2907
- const fd = fs9.openSync(resolved, "r");
3429
+ const fd = fs10.openSync(resolved, "r");
2908
3430
  try {
2909
- fs9.readSync(fd, buf, 0, buf.length, 0);
3431
+ fs10.readSync(fd, buf, 0, buf.length, 0);
2910
3432
  } finally {
2911
- fs9.closeSync(fd);
3433
+ fs10.closeSync(fd);
2912
3434
  }
2913
3435
  return {
2914
3436
  path: resolved,
@@ -2920,23 +3442,23 @@ async function readFile(filePath) {
2920
3442
  }
2921
3443
  async function listFiles(dirPath, opts = {}) {
2922
3444
  const resolved = assertSafePath(dirPath);
2923
- if (!fs9.existsSync(resolved)) {
3445
+ if (!fs10.existsSync(resolved)) {
2924
3446
  throw new Error(`Directory not found: ${resolved}`);
2925
3447
  }
2926
- const stat = fs9.statSync(resolved);
3448
+ const stat = fs10.statSync(resolved);
2927
3449
  if (!stat.isDirectory()) {
2928
3450
  throw new Error(`Path is a file, not a directory: ${resolved}. Use /file read instead.`);
2929
3451
  }
2930
3452
  const entries = [];
2931
3453
  function walk(dir, prefix) {
2932
- const items = fs9.readdirSync(dir, { withFileTypes: true });
3454
+ const items = fs10.readdirSync(dir, { withFileTypes: true });
2933
3455
  for (const item of items) {
2934
3456
  const rel = prefix ? `${prefix}/${item.name}` : item.name;
2935
3457
  if (item.isDirectory()) {
2936
3458
  entries.push({ name: rel, type: "dir", size: 0 });
2937
- if (opts.recursive) walk(path9.join(dir, item.name), rel);
3459
+ if (opts.recursive) walk(path10.join(dir, item.name), rel);
2938
3460
  } else {
2939
- const s = fs9.statSync(path9.join(dir, item.name));
3461
+ const s = fs10.statSync(path10.join(dir, item.name));
2940
3462
  entries.push({ name: rel, type: "file", size: s.size });
2941
3463
  }
2942
3464
  }
@@ -2953,8 +3475,8 @@ init_logger();
2953
3475
  init_logger();
2954
3476
  import pc2 from "picocolors";
2955
3477
  import * as p2 from "@clack/prompts";
2956
- import fs14 from "fs";
2957
- import path14 from "path";
3478
+ import fs15 from "fs";
3479
+ import path15 from "path";
2958
3480
  import os13 from "os";
2959
3481
 
2960
3482
  // src/personality.ts
@@ -3149,13 +3671,13 @@ async function syncPersonalityToCore(state, mcpManager, modelMetrics) {
3149
3671
  }
3150
3672
 
3151
3673
  // src/postmortem.ts
3152
- import fs11 from "fs/promises";
3153
- import path11 from "path";
3674
+ import fs12 from "fs/promises";
3675
+ import path12 from "path";
3154
3676
  import os11 from "os";
3155
3677
 
3156
3678
  // src/observation.ts
3157
- import fs10 from "fs/promises";
3158
- import path10 from "path";
3679
+ import fs11 from "fs/promises";
3680
+ import path11 from "path";
3159
3681
  import os10 from "os";
3160
3682
  var STAT_MAP = {
3161
3683
  tool_call: "toolCalls",
@@ -3166,7 +3688,7 @@ var STAT_MAP = {
3166
3688
  file_change: "fileChanges"
3167
3689
  };
3168
3690
  function defaultObservationsDir() {
3169
- return path10.join(os10.homedir(), ".acore", "observations");
3691
+ return path11.join(os10.homedir(), ".acore", "observations");
3170
3692
  }
3171
3693
  function createObservationSession(sessionId) {
3172
3694
  return {
@@ -3202,17 +3724,17 @@ function resumeObservation(session) {
3202
3724
  async function flushEvents(session, dir) {
3203
3725
  if (session.events.length === 0) return;
3204
3726
  const obsDir = dir ?? defaultObservationsDir();
3205
- await fs10.mkdir(obsDir, { recursive: true });
3206
- const filePath = path10.join(obsDir, `${session.sessionId}.jsonl`);
3727
+ await fs11.mkdir(obsDir, { recursive: true });
3728
+ const filePath = path11.join(obsDir, `${session.sessionId}.jsonl`);
3207
3729
  const lines = session.events.map((e) => JSON.stringify(e)).join("\n") + "\n";
3208
- await fs10.appendFile(filePath, lines, "utf-8");
3730
+ await fs11.appendFile(filePath, lines, "utf-8");
3209
3731
  session.events.length = 0;
3210
3732
  }
3211
3733
  async function readObservationEvents(sessionId, dir) {
3212
3734
  const obsDir = dir ?? defaultObservationsDir();
3213
- const filePath = path10.join(obsDir, `${sessionId}.jsonl`);
3735
+ const filePath = path11.join(obsDir, `${sessionId}.jsonl`);
3214
3736
  try {
3215
- const content = await fs10.readFile(filePath, "utf-8");
3737
+ const content = await fs11.readFile(filePath, "utf-8");
3216
3738
  return content.trim().split("\n").filter((line) => line.length > 0).map((line) => JSON.parse(line));
3217
3739
  } catch {
3218
3740
  return [];
@@ -3235,14 +3757,14 @@ function getSessionStats(session) {
3235
3757
  async function cleanupOldObservations(dir, maxAgeDays = 30) {
3236
3758
  const obsDir = dir ?? defaultObservationsDir();
3237
3759
  try {
3238
- const files = await fs10.readdir(obsDir);
3760
+ const files = await fs11.readdir(obsDir);
3239
3761
  const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
3240
3762
  for (const file of files) {
3241
3763
  if (!file.endsWith(".jsonl")) continue;
3242
- const filePath = path10.join(obsDir, file);
3243
- const stat = await fs10.stat(filePath);
3764
+ const filePath = path11.join(obsDir, file);
3765
+ const stat = await fs11.stat(filePath);
3244
3766
  if (stat.mtimeMs < cutoff) {
3245
- await fs10.unlink(filePath);
3767
+ await fs11.unlink(filePath);
3246
3768
  }
3247
3769
  }
3248
3770
  } catch {
@@ -3269,10 +3791,10 @@ function detectTopicShift(recentMessages, previousMessages) {
3269
3791
  // src/postmortem.ts
3270
3792
  init_logger();
3271
3793
  function defaultPostmortemsDir() {
3272
- return path11.join(os11.homedir(), ".acore", "postmortems");
3794
+ return path12.join(os11.homedir(), ".acore", "postmortems");
3273
3795
  }
3274
3796
  function defaultObservationsDir2() {
3275
- return path11.join(os11.homedir(), ".acore", "observations");
3797
+ return path12.join(os11.homedir(), ".acore", "observations");
3276
3798
  }
3277
3799
  function shouldAutoPostmortem(session, messages) {
3278
3800
  if (messages.length < 6) return false;
@@ -3491,15 +4013,15 @@ function formatPostmortemMarkdown(report) {
3491
4013
  }
3492
4014
  async function savePostmortem(report, dir) {
3493
4015
  const pmDir = dir ?? defaultPostmortemsDir();
3494
- await fs11.mkdir(pmDir, { recursive: true });
4016
+ await fs12.mkdir(pmDir, { recursive: true });
3495
4017
  const shortId = report.sessionId.slice(0, 4);
3496
4018
  const fileName = `${report.date}-${shortId}.md`;
3497
- const filePath = path11.join(pmDir, fileName);
4019
+ const filePath = path12.join(pmDir, fileName);
3498
4020
  const markdown = formatPostmortemMarkdown(report);
3499
- await fs11.writeFile(filePath, markdown, "utf-8");
4021
+ await fs12.writeFile(filePath, markdown, "utf-8");
3500
4022
  const jsonPath = filePath.replace(/\.md$/, ".json");
3501
4023
  try {
3502
- await fs11.writeFile(jsonPath, JSON.stringify(report, null, 2), "utf-8");
4024
+ await fs12.writeFile(jsonPath, JSON.stringify(report, null, 2), "utf-8");
3503
4025
  } catch (err) {
3504
4026
  log.debug("postmortem", "JSON sidecar write failed", err);
3505
4027
  }
@@ -3508,7 +4030,7 @@ async function savePostmortem(report, dir) {
3508
4030
  async function listPostmortems(dir) {
3509
4031
  const pmDir = dir ?? defaultPostmortemsDir();
3510
4032
  try {
3511
- const files = await fs11.readdir(pmDir);
4033
+ const files = await fs12.readdir(pmDir);
3512
4034
  return files.filter((f) => f.endsWith(".md")).sort().reverse();
3513
4035
  } catch {
3514
4036
  return [];
@@ -3518,7 +4040,7 @@ async function readPostmortem(name, dir) {
3518
4040
  const pmDir = dir ?? defaultPostmortemsDir();
3519
4041
  const fileName = name.endsWith(".md") ? name : `${name}.md`;
3520
4042
  try {
3521
- return await fs11.readFile(path11.join(pmDir, fileName), "utf-8");
4043
+ return await fs12.readFile(path12.join(pmDir, fileName), "utf-8");
3522
4044
  } catch {
3523
4045
  return null;
3524
4046
  }
@@ -3565,8 +4087,8 @@ ${contents.join("\n\n---\n\n")}`
3565
4087
 
3566
4088
  // src/crystallization.ts
3567
4089
  init_logger();
3568
- import fs12 from "fs/promises";
3569
- import path12 from "path";
4090
+ import fs13 from "fs/promises";
4091
+ import path13 from "path";
3570
4092
  var STOPWORDS = /* @__PURE__ */ new Set([
3571
4093
  "the",
3572
4094
  "and",
@@ -3731,10 +4253,10 @@ function findCollision(name, triggers, existing) {
3731
4253
  }
3732
4254
  async function writeSkillToFile(candidate, skillsMdPath, postmortemFilename) {
3733
4255
  try {
3734
- await fs12.mkdir(path12.dirname(skillsMdPath), { recursive: true });
4256
+ await fs13.mkdir(path13.dirname(skillsMdPath), { recursive: true });
3735
4257
  let existingContent = "";
3736
4258
  try {
3737
- existingContent = await fs12.readFile(skillsMdPath, "utf-8");
4259
+ existingContent = await fs13.readFile(skillsMdPath, "utf-8");
3738
4260
  } catch {
3739
4261
  existingContent = "# Skills\n\n";
3740
4262
  }
@@ -3755,7 +4277,7 @@ async function writeSkillToFile(candidate, skillsMdPath, postmortemFilename) {
3755
4277
  }
3756
4278
  const skillMarkdown = formatSkillMarkdown(candidate, postmortemFilename);
3757
4279
  const separator = existingContent.endsWith("\n\n") ? "" : existingContent.endsWith("\n") ? "\n" : "\n\n";
3758
- await fs12.writeFile(
4280
+ await fs13.writeFile(
3759
4281
  skillsMdPath,
3760
4282
  existingContent + separator + skillMarkdown,
3761
4283
  "utf-8"
@@ -3777,7 +4299,7 @@ async function writeSkillToFile(candidate, skillsMdPath, postmortemFilename) {
3777
4299
  }
3778
4300
  async function mergeSkillInFile(candidate, existingName, skillsMdPath, postmortemFilename) {
3779
4301
  try {
3780
- const content = await fs12.readFile(skillsMdPath, "utf-8");
4302
+ const content = await fs13.readFile(skillsMdPath, "utf-8");
3781
4303
  const lines = content.split("\n");
3782
4304
  const heading = toTitleCase(existingName);
3783
4305
  let startIdx = -1;
@@ -3818,7 +4340,7 @@ async function mergeSkillInFile(candidate, existingName, skillsMdPath, postmorte
3818
4340
  const before = lines.slice(0, startIdx);
3819
4341
  const after = lines.slice(endIdx);
3820
4342
  const merged = [...before, ...oldBlock, "", newSkillMarkdown, ...after].join("\n");
3821
- await fs12.writeFile(skillsMdPath, merged, "utf-8");
4343
+ await fs13.writeFile(skillsMdPath, merged, "utf-8");
3822
4344
  return {
3823
4345
  written: true,
3824
4346
  filePath: skillsMdPath,
@@ -3837,27 +4359,27 @@ async function mergeSkillInFile(candidate, existingName, skillsMdPath, postmorte
3837
4359
  }
3838
4360
  async function appendCrystallizationLog(entry, logPath) {
3839
4361
  try {
3840
- await fs12.mkdir(path12.dirname(logPath), { recursive: true });
4362
+ await fs13.mkdir(path13.dirname(logPath), { recursive: true });
3841
4363
  let existing = [];
3842
4364
  try {
3843
- const content = await fs12.readFile(logPath, "utf-8");
4365
+ const content = await fs13.readFile(logPath, "utf-8");
3844
4366
  existing = JSON.parse(content);
3845
4367
  if (!Array.isArray(existing)) existing = [];
3846
4368
  } catch {
3847
4369
  existing = [];
3848
4370
  }
3849
4371
  existing.push(entry);
3850
- await fs12.writeFile(logPath, JSON.stringify(existing, null, 2), "utf-8");
4372
+ await fs13.writeFile(logPath, JSON.stringify(existing, null, 2), "utf-8");
3851
4373
  } catch (err) {
3852
4374
  log.debug("crystallization", "appendCrystallizationLog failed", err);
3853
4375
  }
3854
4376
  }
3855
4377
  async function appendRejection(candidate, postmortemFilename, rejectionsPath) {
3856
4378
  try {
3857
- await fs12.mkdir(path12.dirname(rejectionsPath), { recursive: true });
4379
+ await fs13.mkdir(path13.dirname(rejectionsPath), { recursive: true });
3858
4380
  let existing = [];
3859
4381
  try {
3860
- const content = await fs12.readFile(rejectionsPath, "utf-8");
4382
+ const content = await fs13.readFile(rejectionsPath, "utf-8");
3861
4383
  existing = JSON.parse(content);
3862
4384
  if (!Array.isArray(existing)) existing = [];
3863
4385
  } catch {
@@ -3872,14 +4394,14 @@ async function appendRejection(candidate, postmortemFilename, rejectionsPath) {
3872
4394
  while (existing.length > MAX_REJECTIONS) {
3873
4395
  existing.shift();
3874
4396
  }
3875
- await fs12.writeFile(rejectionsPath, JSON.stringify(existing, null, 2), "utf-8");
4397
+ await fs13.writeFile(rejectionsPath, JSON.stringify(existing, null, 2), "utf-8");
3876
4398
  } catch (err) {
3877
4399
  log.debug("crystallization", "appendRejection failed", err);
3878
4400
  }
3879
4401
  }
3880
4402
  async function loadRejectedNames(rejectionsPath) {
3881
4403
  try {
3882
- const content = await fs12.readFile(rejectionsPath, "utf-8");
4404
+ const content = await fs13.readFile(rejectionsPath, "utf-8");
3883
4405
  const entries = JSON.parse(content);
3884
4406
  if (!Array.isArray(entries)) return [];
3885
4407
  return [...new Set(entries.map((e) => e.name))];
@@ -3889,7 +4411,7 @@ async function loadRejectedNames(rejectionsPath) {
3889
4411
  }
3890
4412
  async function loadSuggestionCounts(suggestionsPath) {
3891
4413
  try {
3892
- const content = await fs12.readFile(suggestionsPath, "utf-8");
4414
+ const content = await fs13.readFile(suggestionsPath, "utf-8");
3893
4415
  const parsed = JSON.parse(content);
3894
4416
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
3895
4417
  return parsed;
@@ -3899,10 +4421,10 @@ async function loadSuggestionCounts(suggestionsPath) {
3899
4421
  }
3900
4422
  async function incrementSuggestionCount(name, suggestionsPath) {
3901
4423
  try {
3902
- await fs12.mkdir(path12.dirname(suggestionsPath), { recursive: true });
4424
+ await fs13.mkdir(path13.dirname(suggestionsPath), { recursive: true });
3903
4425
  const counts = await loadSuggestionCounts(suggestionsPath);
3904
4426
  counts[name] = (counts[name] || 0) + 1;
3905
- await fs12.writeFile(suggestionsPath, JSON.stringify(counts, null, 2), "utf-8");
4427
+ await fs13.writeFile(suggestionsPath, JSON.stringify(counts, null, 2), "utf-8");
3906
4428
  return counts[name];
3907
4429
  } catch (err) {
3908
4430
  log.debug("crystallization", "incrementSuggestionCount failed", err);
@@ -4213,10 +4735,10 @@ async function onSessionEnd(ctx, messages, sessionId, observationSession) {
4213
4735
  }
4214
4736
  console.log(pc2.dim(` Saved ${textMessages.length} messages (session: ${sessionId})`));
4215
4737
  }
4216
- const projectContextPath = path14.join(process.cwd(), ".acore", "context.md");
4217
- if (fs14.existsSync(projectContextPath) && messages.length > 2) {
4738
+ const projectContextPath = path15.join(process.cwd(), ".acore", "context.md");
4739
+ if (fs15.existsSync(projectContextPath) && messages.length > 2) {
4218
4740
  try {
4219
- let contextContent = fs14.readFileSync(projectContextPath, "utf-8");
4741
+ let contextContent = fs15.readFileSync(projectContextPath, "utf-8");
4220
4742
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
4221
4743
  let lastUserMsg = "";
4222
4744
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -4234,7 +4756,7 @@ async function onSessionEnd(ctx, messages, sessionId, observationSession) {
4234
4756
  - Recent decisions: [see memory]
4235
4757
  - Temp notes: [cleared]`;
4236
4758
  contextContent = contextContent.replace(sessionPattern, newSession);
4237
- fs14.writeFileSync(projectContextPath, contextContent, "utf-8");
4759
+ fs15.writeFileSync(projectContextPath, contextContent, "utf-8");
4238
4760
  log.debug("hooks", `Updated project context: ${projectContextPath}`);
4239
4761
  }
4240
4762
  } catch (err) {
@@ -4338,7 +4860,7 @@ async function onSessionEnd(ctx, messages, sessionId, observationSession) {
4338
4860
  try {
4339
4861
  const client = ctx.llmClient;
4340
4862
  if (client) {
4341
- const rejectionsPath = path14.join(
4863
+ const rejectionsPath = path15.join(
4342
4864
  os13.homedir(),
4343
4865
  ".aman-agent",
4344
4866
  "crystallization-rejections.json"
@@ -4368,18 +4890,18 @@ async function onSessionEnd(ctx, messages, sessionId, observationSession) {
4368
4890
  }
4369
4891
  }
4370
4892
  if (report.crystallizationCandidates && report.crystallizationCandidates.length > 0) {
4371
- const skillsMdPath = path14.join(os13.homedir(), ".askill", "skills.md");
4372
- const logPath = path14.join(
4893
+ const skillsMdPath = path15.join(os13.homedir(), ".askill", "skills.md");
4894
+ const logPath = path15.join(
4373
4895
  os13.homedir(),
4374
4896
  ".aman-agent",
4375
4897
  "crystallization-log.json"
4376
4898
  );
4377
- const rejectionsPath2 = path14.join(
4899
+ const rejectionsPath2 = path15.join(
4378
4900
  os13.homedir(),
4379
4901
  ".aman-agent",
4380
4902
  "crystallization-rejections.json"
4381
4903
  );
4382
- const suggestionsPath = path14.join(
4904
+ const suggestionsPath = path15.join(
4383
4905
  os13.homedir(),
4384
4906
  ".aman-agent",
4385
4907
  "crystallization-suggestions.json"
@@ -4526,12 +5048,12 @@ You are being delegated a specific task by the primary agent. Complete this task
4526
5048
  </delegation>`;
4527
5049
  let finalDelegationPrompt = delegationPrompt;
4528
5050
  try {
4529
- const recall2 = await memoryRecall(task, { limit: 3, compact: true });
4530
- if (recall2.total > 0) {
5051
+ const recall3 = await memoryRecall(task, { limit: 3, compact: true });
5052
+ if (recall3.total > 0) {
4531
5053
  finalDelegationPrompt += `
4532
5054
 
4533
5055
  <relevant-memories>
4534
- ${recall2.text}
5056
+ ${recall3.text}
4535
5057
  </relevant-memories>`;
4536
5058
  }
4537
5059
  } catch {
@@ -4658,43 +5180,43 @@ import { StreamableHTTPClientTransport as StreamableHTTPClientTransport2 } from
4658
5180
  import { Client as Client3 } from "@modelcontextprotocol/sdk/client/index.js";
4659
5181
 
4660
5182
  // src/teams.ts
4661
- import fs16 from "fs";
4662
- import path16 from "path";
5183
+ import fs17 from "fs";
5184
+ import path17 from "path";
4663
5185
  import os15 from "os";
4664
5186
  import pc4 from "picocolors";
4665
5187
  function getTeamsDir() {
4666
- return path16.join(os15.homedir(), ".acore", "teams");
5188
+ return path17.join(os15.homedir(), ".acore", "teams");
4667
5189
  }
4668
5190
  function ensureTeamsDir() {
4669
5191
  const dir = getTeamsDir();
4670
- if (!fs16.existsSync(dir)) fs16.mkdirSync(dir, { recursive: true });
5192
+ if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
4671
5193
  return dir;
4672
5194
  }
4673
5195
  function teamPath(name) {
4674
5196
  const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
4675
- return path16.join(ensureTeamsDir(), `${slug}.json`);
5197
+ return path17.join(ensureTeamsDir(), `${slug}.json`);
4676
5198
  }
4677
5199
  function createTeam(team) {
4678
5200
  const fp = teamPath(team.name);
4679
- fs16.writeFileSync(fp, JSON.stringify(team, null, 2), "utf-8");
5201
+ fs17.writeFileSync(fp, JSON.stringify(team, null, 2), "utf-8");
4680
5202
  }
4681
5203
  function loadTeam(name) {
4682
5204
  const fp = teamPath(name);
4683
- if (!fs16.existsSync(fp)) return null;
5205
+ if (!fs17.existsSync(fp)) return null;
4684
5206
  try {
4685
- return JSON.parse(fs16.readFileSync(fp, "utf-8"));
5207
+ return JSON.parse(fs17.readFileSync(fp, "utf-8"));
4686
5208
  } catch {
4687
5209
  return null;
4688
5210
  }
4689
5211
  }
4690
5212
  function listTeams() {
4691
5213
  const dir = getTeamsDir();
4692
- if (!fs16.existsSync(dir)) return [];
5214
+ if (!fs17.existsSync(dir)) return [];
4693
5215
  const teams = [];
4694
- for (const file of fs16.readdirSync(dir)) {
5216
+ for (const file of fs17.readdirSync(dir)) {
4695
5217
  if (!file.endsWith(".json")) continue;
4696
5218
  try {
4697
- const content = fs16.readFileSync(path16.join(dir, file), "utf-8");
5219
+ const content = fs17.readFileSync(path17.join(dir, file), "utf-8");
4698
5220
  teams.push(JSON.parse(content));
4699
5221
  } catch {
4700
5222
  }
@@ -4703,8 +5225,8 @@ function listTeams() {
4703
5225
  }
4704
5226
  function deleteTeam(name) {
4705
5227
  const fp = teamPath(name);
4706
- if (!fs16.existsSync(fp)) return false;
4707
- fs16.unlinkSync(fp);
5228
+ if (!fs17.existsSync(fp)) return false;
5229
+ fs17.unlinkSync(fp);
4708
5230
  return true;
4709
5231
  }
4710
5232
  async function runTeam(team, task, client, mcpManager, tools) {
@@ -4931,23 +5453,23 @@ var BUILT_IN_TEAMS = [
4931
5453
 
4932
5454
  // src/plans.ts
4933
5455
  init_logger();
4934
- import fs17 from "fs";
4935
- import path17 from "path";
5456
+ import fs18 from "fs";
5457
+ import path18 from "path";
4936
5458
  import os16 from "os";
4937
5459
  function getPlansDir() {
4938
- const localDir = path17.join(process.cwd(), ".acore", "plans");
4939
- const localAcore = path17.join(process.cwd(), ".acore");
4940
- if (fs17.existsSync(localAcore)) return localDir;
4941
- return path17.join(os16.homedir(), ".acore", "plans");
5460
+ const localDir = path18.join(process.cwd(), ".acore", "plans");
5461
+ const localAcore = path18.join(process.cwd(), ".acore");
5462
+ if (fs18.existsSync(localAcore)) return localDir;
5463
+ return path18.join(os16.homedir(), ".acore", "plans");
4942
5464
  }
4943
5465
  function ensurePlansDir() {
4944
5466
  const dir = getPlansDir();
4945
- if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
5467
+ if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
4946
5468
  return dir;
4947
5469
  }
4948
5470
  function planPath(name) {
4949
5471
  const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
4950
- return path17.join(ensurePlansDir(), `${slug}.md`);
5472
+ return path18.join(ensurePlansDir(), `${slug}.md`);
4951
5473
  }
4952
5474
  function serializePlan(plan) {
4953
5475
  const lines = [];
@@ -4973,7 +5495,7 @@ function parsePlan(content, filePath) {
4973
5495
  const createdMatch = content.match(/\*\*Created:\*\*\s*(.+)/);
4974
5496
  const updatedMatch = content.match(/\*\*Updated:\*\*\s*(.+)/);
4975
5497
  const activeMatch = content.match(/\*\*Active:\*\*\s*(.+)/);
4976
- const name = nameMatch?.[1]?.trim() || path17.basename(filePath, ".md");
5498
+ const name = nameMatch?.[1]?.trim() || path18.basename(filePath, ".md");
4977
5499
  const goal = goalMatch?.[1]?.trim() || "";
4978
5500
  const createdAt = createdMatch?.[1]?.trim() || "";
4979
5501
  const updatedAt = updatedMatch?.[1]?.trim() || "";
@@ -5015,22 +5537,22 @@ function createPlan(name, goal, steps) {
5015
5537
  }
5016
5538
  function savePlan(plan) {
5017
5539
  const fp = planPath(plan.name);
5018
- fs17.writeFileSync(fp, serializePlan(plan), "utf-8");
5540
+ fs18.writeFileSync(fp, serializePlan(plan), "utf-8");
5019
5541
  }
5020
5542
  function loadPlan(name) {
5021
5543
  const fp = planPath(name);
5022
- if (!fs17.existsSync(fp)) return null;
5023
- const content = fs17.readFileSync(fp, "utf-8");
5544
+ if (!fs18.existsSync(fp)) return null;
5545
+ const content = fs18.readFileSync(fp, "utf-8");
5024
5546
  return parsePlan(content, fp);
5025
5547
  }
5026
5548
  function listPlans() {
5027
5549
  const dir = getPlansDir();
5028
- if (!fs17.existsSync(dir)) return [];
5550
+ if (!fs18.existsSync(dir)) return [];
5029
5551
  const plans = [];
5030
- for (const file of fs17.readdirSync(dir)) {
5552
+ for (const file of fs18.readdirSync(dir)) {
5031
5553
  if (!file.endsWith(".md")) continue;
5032
- const fp = path17.join(dir, file);
5033
- const content = fs17.readFileSync(fp, "utf-8");
5554
+ const fp = path18.join(dir, file);
5555
+ const content = fs18.readFileSync(fp, "utf-8");
5034
5556
  const plan = parsePlan(content, fp);
5035
5557
  if (plan) plans.push(plan);
5036
5558
  }
@@ -5129,8 +5651,8 @@ init_user_model();
5129
5651
 
5130
5652
  // src/background.ts
5131
5653
  init_logger();
5132
- import fs18 from "fs";
5133
- import path18 from "path";
5654
+ import fs19 from "fs";
5655
+ import path19 from "path";
5134
5656
  import os17 from "os";
5135
5657
  import pc5 from "picocolors";
5136
5658
  var BACKGROUND_ELIGIBLE = /* @__PURE__ */ new Set([
@@ -5170,13 +5692,13 @@ var NEVER_BACKGROUND = /* @__PURE__ */ new Set([
5170
5692
  "file_list",
5171
5693
  "avatar_prompt"
5172
5694
  ]);
5173
- var TASK_LOG_DIR = path18.join(os17.homedir(), ".aman-agent");
5174
- var TASK_LOG_FILE = path18.join(TASK_LOG_DIR, "bg-tasks.json");
5695
+ var TASK_LOG_DIR = path19.join(os17.homedir(), ".aman-agent");
5696
+ var TASK_LOG_FILE = path19.join(TASK_LOG_DIR, "bg-tasks.json");
5175
5697
  var MAX_LOG_ENTRIES = 50;
5176
5698
  function loadTaskLog() {
5177
5699
  try {
5178
- if (!fs18.existsSync(TASK_LOG_FILE)) return [];
5179
- const raw = fs18.readFileSync(TASK_LOG_FILE, "utf-8");
5700
+ if (!fs19.existsSync(TASK_LOG_FILE)) return [];
5701
+ const raw = fs19.readFileSync(TASK_LOG_FILE, "utf-8");
5180
5702
  return JSON.parse(raw);
5181
5703
  } catch {
5182
5704
  return [];
@@ -5184,9 +5706,9 @@ function loadTaskLog() {
5184
5706
  }
5185
5707
  function saveTaskLog(entries) {
5186
5708
  try {
5187
- if (!fs18.existsSync(TASK_LOG_DIR)) fs18.mkdirSync(TASK_LOG_DIR, { recursive: true });
5709
+ if (!fs19.existsSync(TASK_LOG_DIR)) fs19.mkdirSync(TASK_LOG_DIR, { recursive: true });
5188
5710
  const trimmed = entries.slice(-MAX_LOG_ENTRIES);
5189
- fs18.writeFileSync(TASK_LOG_FILE, JSON.stringify(trimmed, null, 2));
5711
+ fs19.writeFileSync(TASK_LOG_FILE, JSON.stringify(trimmed, null, 2));
5190
5712
  } catch (err) {
5191
5713
  log.debug("background", "Failed to save task log", err);
5192
5714
  }
@@ -5335,10 +5857,10 @@ import {
5335
5857
  } from "@aman_asmuei/arules-core";
5336
5858
  var AGENT_SCOPE = process.env.AMAN_AGENT_SCOPE ?? "dev:agent";
5337
5859
  function readEcosystemFile(filePath, label) {
5338
- if (!fs19.existsSync(filePath)) {
5860
+ if (!fs20.existsSync(filePath)) {
5339
5861
  return pc6.dim(`No ${label} file found at ${filePath}`);
5340
5862
  }
5341
- return fs19.readFileSync(filePath, "utf-8").trim();
5863
+ return fs20.readFileSync(filePath, "utf-8").trim();
5342
5864
  }
5343
5865
  function parseCommand(input) {
5344
5866
  const trimmed = input.trim();
@@ -5423,8 +5945,8 @@ async function handleIdentityCommand(action, args, _ctx) {
5423
5945
  }
5424
5946
  if (args.includes("--reset")) {
5425
5947
  const modelPath = defaultModelPath();
5426
- if (fs19.existsSync(modelPath)) {
5427
- fs19.unlinkSync(modelPath);
5948
+ if (fs20.existsSync(modelPath)) {
5949
+ fs20.unlinkSync(modelPath);
5428
5950
  return { handled: true, output: pc6.green("User model reset. Starting fresh.") };
5429
5951
  }
5430
5952
  return { handled: true, output: pc6.dim("No user model to reset.") };
@@ -5670,7 +6192,7 @@ ${result.violations.map((v) => ` - ${v}`).join("\n")}`)
5670
6192
  async function handleWorkflowsCommand(action, args, ctx) {
5671
6193
  const home2 = os18.homedir();
5672
6194
  if (!action) {
5673
- const content = readEcosystemFile(path19.join(home2, ".aflow", "flow.md"), "workflows (aflow)");
6195
+ const content = readEcosystemFile(path20.join(home2, ".aflow", "flow.md"), "workflows (aflow)");
5674
6196
  return { handled: true, output: content };
5675
6197
  }
5676
6198
  if (action === "add") {
@@ -5692,7 +6214,7 @@ async function handleWorkflowsCommand(action, args, ctx) {
5692
6214
  return { handled: true, output: pc6.yellow("Usage: /workflows get <name>") };
5693
6215
  }
5694
6216
  const name = args.join(" ").toLowerCase();
5695
- const raw = readEcosystemFile(path19.join(home2, ".aflow", "flow.md"), "workflows (aflow)");
6217
+ const raw = readEcosystemFile(path20.join(home2, ".aflow", "flow.md"), "workflows (aflow)");
5696
6218
  if (raw.startsWith("No ")) {
5697
6219
  return { handled: true, output: raw };
5698
6220
  }
@@ -5752,11 +6274,11 @@ async function handleToolsCommand(action, args, _ctx) {
5752
6274
  }
5753
6275
  const query = args.join(" ").toLowerCase();
5754
6276
  const home2 = os18.homedir();
5755
- const toolsFile = path19.join(home2, ".akit", "tools.md");
5756
- if (!fs19.existsSync(toolsFile)) {
6277
+ const toolsFile = path20.join(home2, ".akit", "tools.md");
6278
+ if (!fs20.existsSync(toolsFile)) {
5757
6279
  return { handled: true, output: pc6.dim(`No tools file found. Use 'npx @aman_asmuei/akit search ${args.join(" ")}' to search the registry.`) };
5758
6280
  }
5759
- const raw = fs19.readFileSync(toolsFile, "utf-8").trim();
6281
+ const raw = fs20.readFileSync(toolsFile, "utf-8").trim();
5760
6282
  const lines = raw.split("\n");
5761
6283
  const matches = lines.filter((l) => l.toLowerCase().includes(query));
5762
6284
  if (matches.length === 0) {
@@ -5769,7 +6291,7 @@ async function handleToolsCommand(action, args, _ctx) {
5769
6291
  async function handleSkillsCommand(action, args, ctx) {
5770
6292
  const home2 = os18.homedir();
5771
6293
  if (!action) {
5772
- const content = readEcosystemFile(path19.join(home2, ".askill", "skills.md"), "skills (askill)");
6294
+ const content = readEcosystemFile(path20.join(home2, ".askill", "skills.md"), "skills (askill)");
5773
6295
  return { handled: true, output: content };
5774
6296
  }
5775
6297
  if (action === "install") {
@@ -5792,7 +6314,7 @@ async function handleSkillsCommand(action, args, ctx) {
5792
6314
  }
5793
6315
  const query = args.join(" ").toLowerCase();
5794
6316
  const home3 = os18.homedir();
5795
- const raw = readEcosystemFile(path19.join(home3, ".askill", "skills.md"), "skills (askill)");
6317
+ const raw = readEcosystemFile(path20.join(home3, ".askill", "skills.md"), "skills (askill)");
5796
6318
  if (raw.startsWith("No ")) {
5797
6319
  return { handled: true, output: raw };
5798
6320
  }
@@ -5806,23 +6328,23 @@ async function handleSkillsCommand(action, args, ctx) {
5806
6328
  if (action === "list") {
5807
6329
  const autoOnly = args.includes("--auto");
5808
6330
  if (autoOnly) {
5809
- const logPath = path19.join(os18.homedir(), ".aman-agent", "crystallization-log.json");
6331
+ const logPath = path20.join(os18.homedir(), ".aman-agent", "crystallization-log.json");
5810
6332
  try {
5811
- const content2 = fs19.readFileSync(logPath, "utf-8");
6333
+ const content2 = fs20.readFileSync(logPath, "utf-8");
5812
6334
  const entries = JSON.parse(content2);
5813
6335
  if (entries.length === 0) {
5814
6336
  return { handled: true, output: pc6.dim("No crystallized skills yet.") };
5815
6337
  }
5816
- const suggestionsPath = path19.join(os18.homedir(), ".aman-agent", "crystallization-suggestions.json");
6338
+ const suggestionsPath = path20.join(os18.homedir(), ".aman-agent", "crystallization-suggestions.json");
5817
6339
  let sugCounts = {};
5818
6340
  try {
5819
- const sc = fs19.readFileSync(suggestionsPath, "utf-8");
6341
+ const sc = fs20.readFileSync(suggestionsPath, "utf-8");
5820
6342
  sugCounts = JSON.parse(sc);
5821
6343
  } catch {
5822
6344
  }
5823
6345
  let versionCounts = {};
5824
6346
  try {
5825
- const skillsContent = fs19.readFileSync(path19.join(os18.homedir(), ".askill", "skills.md"), "utf-8");
6347
+ const skillsContent = fs20.readFileSync(path20.join(os18.homedir(), ".askill", "skills.md"), "utf-8");
5826
6348
  const versionRe = /^# (.+)\.v(\d+)$/gm;
5827
6349
  let vMatch;
5828
6350
  while ((vMatch = versionRe.exec(skillsContent)) !== null) {
@@ -5847,13 +6369,13 @@ async function handleSkillsCommand(action, args, ctx) {
5847
6369
  return { handled: true, output: pc6.dim("No crystallized skills yet.") };
5848
6370
  }
5849
6371
  }
5850
- const content = readEcosystemFile(path19.join(home2, ".askill", "skills.md"), "skills (askill)");
6372
+ const content = readEcosystemFile(path20.join(home2, ".askill", "skills.md"), "skills (askill)");
5851
6373
  return { handled: true, output: content };
5852
6374
  }
5853
6375
  if (action === "crystallize") {
5854
- const pmDir = path19.join(os18.homedir(), ".acore", "postmortems");
6376
+ const pmDir = path20.join(os18.homedir(), ".acore", "postmortems");
5855
6377
  try {
5856
- const files = fs19.readdirSync(pmDir);
6378
+ const files = fs20.readdirSync(pmDir);
5857
6379
  const jsonFiles = files.filter((f) => f.endsWith(".json")).sort().reverse();
5858
6380
  if (jsonFiles.length === 0) {
5859
6381
  return {
@@ -5862,7 +6384,7 @@ async function handleSkillsCommand(action, args, ctx) {
5862
6384
  };
5863
6385
  }
5864
6386
  const latest = jsonFiles[0];
5865
- const content = fs19.readFileSync(path19.join(pmDir, latest), "utf-8");
6387
+ const content = fs20.readFileSync(path20.join(pmDir, latest), "utf-8");
5866
6388
  const report = JSON.parse(content);
5867
6389
  if (!report.crystallizationCandidates || report.crystallizationCandidates.length === 0) {
5868
6390
  return {
@@ -5870,8 +6392,8 @@ async function handleSkillsCommand(action, args, ctx) {
5870
6392
  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
6393
  };
5872
6394
  }
5873
- const skillsMdPath = path19.join(os18.homedir(), ".askill", "skills.md");
5874
- const logPath = path19.join(os18.homedir(), ".aman-agent", "crystallization-log.json");
6395
+ const skillsMdPath = path20.join(os18.homedir(), ".askill", "skills.md");
6396
+ const logPath = path20.join(os18.homedir(), ".aman-agent", "crystallization-log.json");
5875
6397
  const postmortemFilename = latest.replace(/\.json$/, ".md");
5876
6398
  const lines = [
5877
6399
  pc6.bold(`Found ${report.crystallizationCandidates.length} candidate(s) in ${latest}:`)
@@ -5930,7 +6452,7 @@ async function handleSkillsCommand(action, args, ctx) {
5930
6452
  async function handleEvalCommand(action, args, ctx) {
5931
6453
  const home2 = os18.homedir();
5932
6454
  if (!action) {
5933
- const content = readEcosystemFile(path19.join(home2, ".aeval", "eval.md"), "evaluation (aeval)");
6455
+ const content = readEcosystemFile(path20.join(home2, ".aeval", "eval.md"), "evaluation (aeval)");
5934
6456
  return { handled: true, output: content };
5935
6457
  }
5936
6458
  if (action === "milestone") {
@@ -5942,10 +6464,10 @@ async function handleEvalCommand(action, args, ctx) {
5942
6464
  return { handled: true, output };
5943
6465
  }
5944
6466
  if (action === "report") {
5945
- const evalFile = path19.join(home2, ".aeval", "eval.md");
6467
+ const evalFile = path20.join(home2, ".aeval", "eval.md");
5946
6468
  const lines = [pc6.bold("\u{1F4CA} Eval Report")];
5947
- if (fs19.existsSync(evalFile)) {
5948
- lines.push("", fs19.readFileSync(evalFile, "utf-8").trim());
6469
+ if (fs20.existsSync(evalFile)) {
6470
+ lines.push("", fs20.readFileSync(evalFile, "utf-8").trim());
5949
6471
  } else {
5950
6472
  lines.push("", pc6.dim("No eval log yet. Use /eval milestone <text> to start."));
5951
6473
  }
@@ -6503,10 +7025,10 @@ function handleSave() {
6503
7025
  }
6504
7026
  function handleReset(action) {
6505
7027
  const dirs = {
6506
- config: path19.join(os18.homedir(), ".aman-agent"),
6507
- memory: path19.join(os18.homedir(), ".amem"),
6508
- identity: path19.join(os18.homedir(), ".acore"),
6509
- rules: path19.join(os18.homedir(), ".arules")
7028
+ config: path20.join(os18.homedir(), ".aman-agent"),
7029
+ memory: path20.join(os18.homedir(), ".amem"),
7030
+ identity: path20.join(os18.homedir(), ".acore"),
7031
+ rules: path20.join(os18.homedir(), ".arules")
6510
7032
  };
6511
7033
  if (action === "help" || !action) {
6512
7034
  return {
@@ -6531,15 +7053,15 @@ function handleReset(action) {
6531
7053
  const removed = [];
6532
7054
  for (const target of targets) {
6533
7055
  const dir = dirs[target];
6534
- if (fs19.existsSync(dir)) {
6535
- fs19.rmSync(dir, { recursive: true, force: true });
7056
+ if (fs20.existsSync(dir)) {
7057
+ fs20.rmSync(dir, { recursive: true, force: true });
6536
7058
  removed.push(target);
6537
7059
  }
6538
7060
  }
6539
7061
  if (targets.includes("config")) {
6540
7062
  const configDir2 = dirs.config;
6541
- fs19.mkdirSync(configDir2, { recursive: true });
6542
- fs19.writeFileSync(path19.join(configDir2, ".reconfig"), "", "utf-8");
7063
+ fs20.mkdirSync(configDir2, { recursive: true });
7064
+ fs20.writeFileSync(path20.join(configDir2, ".reconfig"), "", "utf-8");
6543
7065
  }
6544
7066
  if (removed.length === 0) {
6545
7067
  return { handled: true, output: pc6.dim("Nothing to reset \u2014 directories don't exist.") };
@@ -6556,20 +7078,19 @@ function handleReset(action) {
6556
7078
  function handleUpdate() {
6557
7079
  try {
6558
7080
  const current = execFileSync3("npm", ["view", "@aman_asmuei/aman-agent", "version"], { encoding: "utf-8" }).trim();
6559
- const local = true ? "0.31.0" : "unknown";
7081
+ const local = true ? "0.33.0" : "unknown";
6560
7082
  if (current === local) {
6561
7083
  return { handled: true, output: `${pc6.green("Up to date")} \u2014 v${local}` };
6562
7084
  }
7085
+ const isVendored = process.execPath.includes(path20.join(".aman-agent", "node"));
7086
+ const updateCmd = isVendored ? "aman-agent update" : "npm install -g @aman_asmuei/aman-agent@latest";
6563
7087
  return {
6564
7088
  handled: true,
6565
7089
  output: [
6566
7090
  `${pc6.yellow("Update available:")} v${local} \u2192 v${current}`,
6567
7091
  "",
6568
7092
  `Run this in your terminal:`,
6569
- ` ${pc6.bold("npm install -g @aman_asmuei/aman-agent@latest")}`,
6570
- "",
6571
- `Or use npx (always latest):`,
6572
- ` ${pc6.bold("npx @aman_asmuei/aman-agent@latest")}`
7093
+ ` ${pc6.bold(updateCmd)}`
6573
7094
  ].join("\n")
6574
7095
  };
6575
7096
  } catch {
@@ -6577,10 +7098,7 @@ function handleUpdate() {
6577
7098
  handled: true,
6578
7099
  output: [
6579
7100
  `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")}`
7101
+ ` ${pc6.bold("npm install -g @aman_asmuei/aman-agent@latest")}`
6584
7102
  ].join("\n")
6585
7103
  };
6586
7104
  }
@@ -6600,11 +7118,11 @@ function handleExportCommand() {
6600
7118
  return { handled: true, exportConversation: true };
6601
7119
  }
6602
7120
  function handleDebugCommand() {
6603
- const logPath = path19.join(os18.homedir(), ".aman-agent", "debug.log");
6604
- if (!fs19.existsSync(logPath)) {
7121
+ const logPath = path20.join(os18.homedir(), ".aman-agent", "debug.log");
7122
+ if (!fs20.existsSync(logPath)) {
6605
7123
  return { handled: true, output: pc6.dim("No debug log found.") };
6606
7124
  }
6607
- const content = fs19.readFileSync(logPath, "utf-8");
7125
+ const content = fs20.readFileSync(logPath, "utf-8");
6608
7126
  const lines = content.trim().split("\n");
6609
7127
  const last20 = lines.slice(-20).join("\n");
6610
7128
  return { handled: true, output: pc6.bold("Debug Log (last 20 entries):\n") + pc6.dim(last20) };
@@ -6884,7 +7402,7 @@ ${text3}` };
6884
7402
  };
6885
7403
  }
6886
7404
  function handleProfileCommand(action, args) {
6887
- const profilesDir = path19.join(os18.homedir(), ".acore", "profiles");
7405
+ const profilesDir = path20.join(os18.homedir(), ".acore", "profiles");
6888
7406
  if (action === "me") {
6889
7407
  const user = loadUserIdentity();
6890
7408
  if (!user) {
@@ -6952,8 +7470,8 @@ ${pc6.dim("Edit with: /profile edit")}` };
6952
7470
  };
6953
7471
  }
6954
7472
  const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
6955
- const profileDir = path19.join(profilesDir, slug);
6956
- if (fs19.existsSync(profileDir)) {
7473
+ const profileDir = path20.join(profilesDir, slug);
7474
+ if (fs20.existsSync(profileDir)) {
6957
7475
  return { handled: true, output: pc6.yellow(`Profile already exists: ${slug}`) };
6958
7476
  }
6959
7477
  const builtIn = BUILT_IN_PROFILES.find((t) => t.name === slug);
@@ -6969,16 +7487,16 @@ ${pc6.dim("Edit with: /profile edit")}` };
6969
7487
  Use: aman-agent --profile ${slug}`
6970
7488
  };
6971
7489
  }
6972
- fs19.mkdirSync(profileDir, { recursive: true });
6973
- const globalCore = path19.join(os18.homedir(), ".acore", "core.md");
6974
- if (fs19.existsSync(globalCore)) {
6975
- let content = fs19.readFileSync(globalCore, "utf-8");
7490
+ fs20.mkdirSync(profileDir, { recursive: true });
7491
+ const globalCore = path20.join(os18.homedir(), ".acore", "core.md");
7492
+ if (fs20.existsSync(globalCore)) {
7493
+ let content = fs20.readFileSync(globalCore, "utf-8");
6976
7494
  const aiName = name.charAt(0).toUpperCase() + name.slice(1);
6977
7495
  content = content.replace(/^# .+$/m, `# ${aiName}`);
6978
- fs19.writeFileSync(path19.join(profileDir, "core.md"), content, "utf-8");
7496
+ fs20.writeFileSync(path20.join(profileDir, "core.md"), content, "utf-8");
6979
7497
  } else {
6980
7498
  const aiName = name.charAt(0).toUpperCase() + name.slice(1);
6981
- fs19.writeFileSync(path19.join(profileDir, "core.md"), `# ${aiName}
7499
+ fs20.writeFileSync(path20.join(profileDir, "core.md"), `# ${aiName}
6982
7500
 
6983
7501
  ## Identity
6984
7502
  - Role: ${aiName} is your AI companion
@@ -6991,7 +7509,7 @@ ${pc6.dim("Edit with: /profile edit")}` };
6991
7509
  return {
6992
7510
  handled: true,
6993
7511
  output: pc6.green(`Profile created: ${slug}`) + `
6994
- Edit: ${path19.join(profileDir, "core.md")}
7512
+ Edit: ${path20.join(profileDir, "core.md")}
6995
7513
  Use: aman-agent --profile ${slug}
6996
7514
 
6997
7515
  ${pc6.dim("Add rules.md or skills.md for profile-specific overrides.")}`
@@ -7000,9 +7518,9 @@ ${pc6.dim("Edit with: /profile edit")}` };
7000
7518
  case "show": {
7001
7519
  const name = args[0];
7002
7520
  if (!name) return { handled: true, output: pc6.yellow("Usage: /profile show <name>") };
7003
- const profileDir = path19.join(profilesDir, name);
7004
- if (!fs19.existsSync(profileDir)) return { handled: true, output: pc6.red(`Profile not found: ${name}`) };
7005
- const files = fs19.readdirSync(profileDir).filter((f) => f.endsWith(".md"));
7521
+ const profileDir = path20.join(profilesDir, name);
7522
+ if (!fs20.existsSync(profileDir)) return { handled: true, output: pc6.red(`Profile not found: ${name}`) };
7523
+ const files = fs20.readdirSync(profileDir).filter((f) => f.endsWith(".md"));
7006
7524
  const lines = files.map((f) => ` ${f}`);
7007
7525
  return { handled: true, output: `Profile: ${pc6.bold(name)}
7008
7526
  Files:
@@ -7011,9 +7529,9 @@ ${lines.join("\n")}` };
7011
7529
  case "delete": {
7012
7530
  const name = args[0];
7013
7531
  if (!name) return { handled: true, output: pc6.yellow("Usage: /profile delete <name>") };
7014
- const profileDir = path19.join(profilesDir, name);
7015
- if (!fs19.existsSync(profileDir)) return { handled: true, output: pc6.red(`Profile not found: ${name}`) };
7016
- fs19.rmSync(profileDir, { recursive: true });
7532
+ const profileDir = path20.join(profilesDir, name);
7533
+ if (!fs20.existsSync(profileDir)) return { handled: true, output: pc6.red(`Profile not found: ${name}`) };
7534
+ fs20.rmSync(profileDir, { recursive: true });
7017
7535
  return { handled: true, output: pc6.dim(`Profile deleted: ${name}`) };
7018
7536
  }
7019
7537
  case "help":
@@ -7231,10 +7749,10 @@ function handleShowcaseCommand(action, args) {
7231
7749
  Or place it as a sibling directory to aman-agent.`
7232
7750
  };
7233
7751
  }
7234
- const corePath = path19.join(os18.homedir(), ".acore", "core.md");
7752
+ const corePath = path20.join(os18.homedir(), ".acore", "core.md");
7235
7753
  let currentShowcase = null;
7236
- if (fs19.existsSync(corePath)) {
7237
- const content = fs19.readFileSync(corePath, "utf-8");
7754
+ if (fs20.existsSync(corePath)) {
7755
+ const content = fs20.readFileSync(corePath, "utf-8");
7238
7756
  const nameMatch = content.match(/^# (.+)/m);
7239
7757
  if (nameMatch) {
7240
7758
  const coreName = nameMatch[1].trim().toLowerCase();
@@ -7632,9 +8150,9 @@ init_logger();
7632
8150
 
7633
8151
  // src/skill-engine.ts
7634
8152
  init_logger();
7635
- import fs20 from "fs";
8153
+ import fs21 from "fs";
7636
8154
  import fsp from "fs/promises";
7637
- import path20 from "path";
8155
+ import path21 from "path";
7638
8156
  import os19 from "os";
7639
8157
  var SKILL_TRIGGERS = {
7640
8158
  testing: ["test", "spec", "coverage", "tdd", "jest", "vitest", "mocha", "assert", "mock", "stub", "fixture", "e2e", "integration test", "unit test"],
@@ -7664,20 +8182,20 @@ async function loadRuntimeTriggers(skillsMdPath) {
7664
8182
  return /* @__PURE__ */ new Map();
7665
8183
  }
7666
8184
  }
7667
- var LEVEL_FILE = path20.join(os19.homedir(), ".aman-agent", "skill-levels.json");
8185
+ var LEVEL_FILE = path21.join(os19.homedir(), ".aman-agent", "skill-levels.json");
7668
8186
  function loadSkillLevels() {
7669
8187
  try {
7670
- if (fs20.existsSync(LEVEL_FILE)) {
7671
- return JSON.parse(fs20.readFileSync(LEVEL_FILE, "utf-8"));
8188
+ if (fs21.existsSync(LEVEL_FILE)) {
8189
+ return JSON.parse(fs21.readFileSync(LEVEL_FILE, "utf-8"));
7672
8190
  }
7673
8191
  } catch {
7674
8192
  }
7675
8193
  return {};
7676
8194
  }
7677
8195
  function saveSkillLevels(levels) {
7678
- const dir = path20.dirname(LEVEL_FILE);
7679
- if (!fs20.existsSync(dir)) fs20.mkdirSync(dir, { recursive: true });
7680
- fs20.writeFileSync(LEVEL_FILE, JSON.stringify(levels, null, 2), "utf-8");
8196
+ const dir = path21.dirname(LEVEL_FILE);
8197
+ if (!fs21.existsSync(dir)) fs21.mkdirSync(dir, { recursive: true });
8198
+ fs21.writeFileSync(LEVEL_FILE, JSON.stringify(levels, null, 2), "utf-8");
7681
8199
  }
7682
8200
  function computeLevel(activations) {
7683
8201
  if (activations >= 50) return { level: 5, label: "Expert" };
@@ -7904,7 +8422,7 @@ async function autoTriggerSkills(userInput, mcpManager) {
7904
8422
  const result = await mcpManager.callTool("skill_list", {});
7905
8423
  const skills = JSON.parse(result);
7906
8424
  const installed = skills.filter((s) => s.installed).map((s) => s.name);
7907
- const skillsMdPath = path20.join(os19.homedir(), ".askill", "skills.md");
8425
+ const skillsMdPath = path21.join(os19.homedir(), ".askill", "skills.md");
7908
8426
  const runtimeTriggers = await loadRuntimeTriggers(skillsMdPath);
7909
8427
  if (installed.length === 0 && runtimeTriggers.size === 0) return "";
7910
8428
  const matched = matchSkillsSemantic(userInput, installed, runtimeTriggers);
@@ -8337,6 +8855,9 @@ Assistant: ${assistantResponse.slice(0, 2e3)}`;
8337
8855
  }
8338
8856
  }
8339
8857
 
8858
+ // src/agent.ts
8859
+ init_token_budget();
8860
+
8340
8861
  // src/errors.ts
8341
8862
  var ERROR_MAPPINGS = [
8342
8863
  { pattern: /rate.?limit|429/i, message: "Rate limited. I'll retry automatically." },
@@ -8358,8 +8879,8 @@ function humanizeError(message) {
8358
8879
  }
8359
8880
 
8360
8881
  // src/hints.ts
8361
- import fs21 from "fs";
8362
- import path21 from "path";
8882
+ import fs22 from "fs";
8883
+ import path22 from "path";
8363
8884
  import os20 from "os";
8364
8885
  var HINTS = [
8365
8886
  {
@@ -8398,11 +8919,11 @@ function getHint(state, ctx) {
8398
8919
  }
8399
8920
  return null;
8400
8921
  }
8401
- var HINTS_FILE = path21.join(os20.homedir(), ".aman-agent", "hints-seen.json");
8922
+ var HINTS_FILE = path22.join(os20.homedir(), ".aman-agent", "hints-seen.json");
8402
8923
  function loadShownHints() {
8403
8924
  try {
8404
- if (fs21.existsSync(HINTS_FILE)) {
8405
- const data = JSON.parse(fs21.readFileSync(HINTS_FILE, "utf-8"));
8925
+ if (fs22.existsSync(HINTS_FILE)) {
8926
+ const data = JSON.parse(fs22.readFileSync(HINTS_FILE, "utf-8"));
8406
8927
  return new Set(Array.isArray(data) ? data : []);
8407
8928
  }
8408
8929
  } catch {
@@ -8411,9 +8932,9 @@ function loadShownHints() {
8411
8932
  }
8412
8933
  function saveShownHints(shown) {
8413
8934
  try {
8414
- const dir = path21.dirname(HINTS_FILE);
8415
- fs21.mkdirSync(dir, { recursive: true });
8416
- fs21.writeFileSync(HINTS_FILE, JSON.stringify([...shown]), "utf-8");
8935
+ const dir = path22.dirname(HINTS_FILE);
8936
+ fs22.mkdirSync(dir, { recursive: true });
8937
+ fs22.writeFileSync(HINTS_FILE, JSON.stringify([...shown]), "utf-8");
8417
8938
  } catch {
8418
8939
  }
8419
8940
  }
@@ -8680,9 +9201,9 @@ ${task.result}`
8680
9201
  }
8681
9202
  if (cmdResult.exportConversation) {
8682
9203
  try {
8683
- const exportDir = path22.join(os21.homedir(), ".aman-agent", "exports");
8684
- fs22.mkdirSync(exportDir, { recursive: true });
8685
- const exportPath = path22.join(exportDir, `${sessionId}.md`);
9204
+ const exportDir = path23.join(os21.homedir(), ".aman-agent", "exports");
9205
+ fs23.mkdirSync(exportDir, { recursive: true });
9206
+ const exportPath = path23.join(exportDir, `${sessionId}.md`);
8686
9207
  const lines = [
8687
9208
  `# Conversation \u2014 ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
8688
9209
  `**Model:** ${model}`,
@@ -8696,7 +9217,7 @@ ${task.result}`
8696
9217
  lines.push(`${label} ${msg.content}`, "");
8697
9218
  }
8698
9219
  }
8699
- fs22.writeFileSync(exportPath, lines.join("\n"), "utf-8");
9220
+ fs23.writeFileSync(exportPath, lines.join("\n"), "utf-8");
8700
9221
  console.log(pc7.green(`Exported to ${exportPath}`));
8701
9222
  } catch {
8702
9223
  console.log(pc7.red("Failed to export conversation."));
@@ -8822,25 +9343,25 @@ ${knowledgeItem.content}
8822
9343
  for (const match of filePathMatches) {
8823
9344
  let filePath = match[1];
8824
9345
  if (filePath.startsWith("~/")) {
8825
- filePath = path22.join(os21.homedir(), filePath.slice(2));
9346
+ filePath = path23.join(os21.homedir(), filePath.slice(2));
8826
9347
  }
8827
- if (!fs22.existsSync(filePath) || !fs22.statSync(filePath).isFile()) continue;
8828
- const ext = path22.extname(filePath).toLowerCase();
9348
+ if (!fs23.existsSync(filePath) || !fs23.statSync(filePath).isFile()) continue;
9349
+ const ext = path23.extname(filePath).toLowerCase();
8829
9350
  if (imageExts.has(ext)) {
8830
9351
  try {
8831
- const stat = fs22.statSync(filePath);
9352
+ const stat = fs23.statSync(filePath);
8832
9353
  if (stat.size > maxImageBytes) {
8833
- process.stdout.write(pc7.yellow(` [skipped: ${path22.basename(filePath)} \u2014 exceeds 20MB limit]
9354
+ process.stdout.write(pc7.yellow(` [skipped: ${path23.basename(filePath)} \u2014 exceeds 20MB limit]
8834
9355
  `));
8835
9356
  continue;
8836
9357
  }
8837
- const data = fs22.readFileSync(filePath).toString("base64");
9358
+ const data = fs23.readFileSync(filePath).toString("base64");
8838
9359
  const mediaType = mimeMap[ext] || "image/png";
8839
9360
  imageBlocks.push({
8840
9361
  type: "image",
8841
9362
  source: { type: "base64", media_type: mediaType, data }
8842
9363
  });
8843
- process.stdout.write(pc7.dim(` [attached image: ${path22.basename(filePath)} (${(stat.size / 1024).toFixed(1)}KB)]
9364
+ process.stdout.write(pc7.dim(` [attached image: ${path23.basename(filePath)} (${(stat.size / 1024).toFixed(1)}KB)]
8844
9365
  `));
8845
9366
  } catch {
8846
9367
  process.stdout.write(pc7.dim(` [could not read image: ${filePath}]
@@ -8848,7 +9369,7 @@ ${knowledgeItem.content}
8848
9369
  }
8849
9370
  } else if (textExts.has(ext) || ext === "") {
8850
9371
  try {
8851
- const content = fs22.readFileSync(filePath, "utf-8");
9372
+ const content = fs23.readFileSync(filePath, "utf-8");
8852
9373
  const maxChars = 5e4;
8853
9374
  const trimmed = content.length > maxChars ? content.slice(0, maxChars) + `
8854
9375
 
@@ -8858,7 +9379,7 @@ ${knowledgeItem.content}
8858
9379
  <file path="${filePath}" size="${content.length} chars">
8859
9380
  ${trimmed}
8860
9381
  </file>`;
8861
- process.stdout.write(pc7.dim(` [attached: ${path22.basename(filePath)} (${(content.length / 1024).toFixed(1)}KB)]
9382
+ process.stdout.write(pc7.dim(` [attached: ${path23.basename(filePath)} (${(content.length / 1024).toFixed(1)}KB)]
8862
9383
  `));
8863
9384
  } catch {
8864
9385
  process.stdout.write(pc7.dim(` [could not read: ${filePath}]
@@ -8867,7 +9388,7 @@ ${trimmed}
8867
9388
  } else if (docExts.has(ext)) {
8868
9389
  if (mcpManager) {
8869
9390
  try {
8870
- process.stdout.write(pc7.dim(` [converting: ${path22.basename(filePath)}...]
9391
+ process.stdout.write(pc7.dim(` [converting: ${path23.basename(filePath)}...]
8871
9392
  `));
8872
9393
  const converted = await mcpManager.callTool("doc_convert", { path: filePath });
8873
9394
  if (converted && !converted.startsWith("Error") && !converted.includes("Could not convert")) {
@@ -8876,7 +9397,7 @@ ${trimmed}
8876
9397
  <file path="${filePath}" format="${ext}">
8877
9398
  ${converted.slice(0, 5e4)}
8878
9399
  </file>`;
8879
- process.stdout.write(pc7.dim(` [attached: ${path22.basename(filePath)} (converted from ${ext})]
9400
+ process.stdout.write(pc7.dim(` [attached: ${path23.basename(filePath)} (converted from ${ext})]
8880
9401
  `));
8881
9402
  } else {
8882
9403
  textContent += `
@@ -8888,7 +9409,7 @@ ${converted}
8888
9409
  `));
8889
9410
  }
8890
9411
  } catch {
8891
- process.stdout.write(pc7.dim(` [could not convert: ${path22.basename(filePath)}]
9412
+ process.stdout.write(pc7.dim(` [could not convert: ${path23.basename(filePath)}]
8892
9413
  `));
8893
9414
  }
8894
9415
  } else {
@@ -8944,10 +9465,10 @@ ${converted}
8944
9465
  let augmentedSystemPrompt = activeSystemPrompt;
8945
9466
  let memoryTokens = 0;
8946
9467
  {
8947
- const recall2 = await recallForMessage(input);
8948
- if (recall2) {
8949
- augmentedSystemPrompt = activeSystemPrompt + recall2.text;
8950
- memoryTokens = recall2.tokenEstimate;
9468
+ const recall3 = await recallForMessage(input);
9469
+ if (recall3) {
9470
+ augmentedSystemPrompt = activeSystemPrompt + recall3.text;
9471
+ memoryTokens = recall3.tokenEstimate;
8951
9472
  }
8952
9473
  }
8953
9474
  const userTurnCount = messages.filter((m) => m.role === "user").length;
@@ -9280,7 +9801,7 @@ ${result2.response}` : `[${input2.profile}] failed: ${result2.error}`;
9280
9801
  }
9281
9802
  if (hooksConfig?.featureHints) {
9282
9803
  hintState.turnCount++;
9283
- const hasWorkflows = fs22.existsSync(path22.join(os21.homedir(), ".aflow", "flow.md"));
9804
+ const hasWorkflows = fs23.existsSync(path23.join(os21.homedir(), ".aflow", "flow.md"));
9284
9805
  const memoryCount = memoryTokens > 0 ? Math.floor(memoryTokens / 5) : 0;
9285
9806
  const hint = getHint(hintState, { hasWorkflows, memoryCount });
9286
9807
  if (hint) {
@@ -9326,9 +9847,8 @@ async function saveConversationToMemory(messages, sessionId) {
9326
9847
  }
9327
9848
 
9328
9849
  // src/index.ts
9329
- import fs23 from "fs";
9330
- import path23 from "path";
9331
- import os22 from "os";
9850
+ import fs27 from "fs";
9851
+ import path28 from "path";
9332
9852
 
9333
9853
  // src/presets.ts
9334
9854
  var PRESETS = {
@@ -9542,9 +10062,12 @@ var Inbox = class {
9542
10062
  // package.json
9543
10063
  var package_default = {
9544
10064
  name: "@aman_asmuei/aman-agent",
9545
- version: "0.31.0",
10065
+ version: "0.33.0",
9546
10066
  description: "Your AI companion, running locally \u2014 powered by the aman ecosystem",
9547
10067
  type: "module",
10068
+ engines: {
10069
+ node: ">=18.0.0"
10070
+ },
9548
10071
  bin: {
9549
10072
  "aman-agent": "./bin/aman-agent.js"
9550
10073
  },
@@ -9832,9 +10355,9 @@ async function runServe(opts) {
9832
10355
 
9833
10356
  // src/index.ts
9834
10357
  async function autoDetectConfig() {
9835
- const reconfigMarker = path23.join(os22.homedir(), ".aman-agent", ".reconfig");
9836
- if (fs23.existsSync(reconfigMarker)) {
9837
- fs23.unlinkSync(reconfigMarker);
10358
+ const reconfigMarker = path28.join(homeDir(), ".reconfig");
10359
+ if (fs27.existsSync(reconfigMarker)) {
10360
+ fs27.unlinkSync(reconfigMarker);
9838
10361
  return null;
9839
10362
  }
9840
10363
  const anthropicKey = process.env.ANTHROPIC_API_KEY;
@@ -9863,11 +10386,10 @@ async function autoDetectConfig() {
9863
10386
  return null;
9864
10387
  }
9865
10388
  function bootstrapEcosystem() {
9866
- const home2 = os22.homedir();
9867
- const corePath = path23.join(home2, ".acore", "core.md");
9868
- if (fs23.existsSync(corePath)) return false;
9869
- fs23.mkdirSync(path23.join(home2, ".acore"), { recursive: true });
9870
- fs23.writeFileSync(corePath, [
10389
+ const corePath = path28.join(identityDir(), "core.md");
10390
+ if (fs27.existsSync(corePath)) return false;
10391
+ fs27.mkdirSync(identityDir(), { recursive: true });
10392
+ fs27.writeFileSync(corePath, [
9871
10393
  "# Aman",
9872
10394
  "",
9873
10395
  "## Personality",
@@ -9879,11 +10401,10 @@ function bootstrapEcosystem() {
9879
10401
  "## Session",
9880
10402
  "_New companion \u2014 no prior sessions._"
9881
10403
  ].join("\n"), "utf-8");
9882
- const rulesDir = path23.join(home2, ".arules");
9883
- const rulesPath = path23.join(rulesDir, "rules.md");
9884
- if (!fs23.existsSync(rulesPath)) {
9885
- fs23.mkdirSync(rulesDir, { recursive: true });
9886
- fs23.writeFileSync(rulesPath, [
10404
+ const rulesPath = path28.join(rulesDir(), "rules.md");
10405
+ if (!fs27.existsSync(rulesPath)) {
10406
+ fs27.mkdirSync(rulesDir(), { recursive: true });
10407
+ fs27.writeFileSync(rulesPath, [
9887
10408
  "# Guardrails",
9888
10409
  "",
9889
10410
  "## safety",
@@ -9895,22 +10416,20 @@ function bootstrapEcosystem() {
9895
10416
  "- Respect the user's preferences stored in memory"
9896
10417
  ].join("\n"), "utf-8");
9897
10418
  }
9898
- const flowDir = path23.join(home2, ".aflow");
9899
- const flowPath = path23.join(flowDir, "flow.md");
9900
- if (!fs23.existsSync(flowPath)) {
9901
- fs23.mkdirSync(flowDir, { recursive: true });
9902
- fs23.writeFileSync(flowPath, "# Workflows\n\n_No workflows defined yet. Use /workflows add to create one._\n", "utf-8");
10419
+ const flowPath = path28.join(workflowsDir(), "flow.md");
10420
+ if (!fs27.existsSync(flowPath)) {
10421
+ fs27.mkdirSync(workflowsDir(), { recursive: true });
10422
+ fs27.writeFileSync(flowPath, "# Workflows\n\n_No workflows defined yet. Use /workflows add to create one._\n", "utf-8");
9903
10423
  }
9904
- const skillDir = path23.join(home2, ".askill");
9905
- const skillPath = path23.join(skillDir, "skills.md");
9906
- if (!fs23.existsSync(skillPath)) {
9907
- fs23.mkdirSync(skillDir, { recursive: true });
9908
- fs23.writeFileSync(skillPath, "# Skills\n\n_No skills installed yet. Use /skills install to add domain expertise._\n", "utf-8");
10424
+ const skillPath = path28.join(skillsDir(), "skills.md");
10425
+ if (!fs27.existsSync(skillPath)) {
10426
+ fs27.mkdirSync(skillsDir(), { recursive: true });
10427
+ fs27.writeFileSync(skillPath, "# Skills\n\n_No skills installed yet. Use /skills install to add domain expertise._\n", "utf-8");
9909
10428
  }
9910
10429
  return true;
9911
10430
  }
9912
10431
  var program = new Command();
9913
- program.name("aman-agent").description("Your AI companion, running locally").version("0.31.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) => {
10432
+ program.name("aman-agent").description("Your AI companion, running locally").version("0.33.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
10433
  p4.intro(pc9.bold("aman agent") + pc9.dim(" \u2014 your AI companion"));
9915
10434
  let config = loadConfig();
9916
10435
  if (!config) {
@@ -9922,6 +10441,11 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
9922
10441
  p4.log.info(pc9.dim("Change anytime with /reset config"));
9923
10442
  saveConfig(config);
9924
10443
  } else {
10444
+ if (!process.stdin.isTTY) {
10445
+ console.error("Error: No LLM provider configured.");
10446
+ console.error("Set ANTHROPIC_API_KEY or OPENAI_API_KEY, or run interactively: aman-agent");
10447
+ process.exit(1);
10448
+ }
9925
10449
  p4.log.info("First-time setup \u2014 configure your LLM connection.");
9926
10450
  const provider = await p4.select({
9927
10451
  message: "LLM provider",
@@ -10134,6 +10658,15 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
10134
10658
  const model = options.model || config.model;
10135
10659
  const s = p4.spinner();
10136
10660
  s.start("Loading ecosystem");
10661
+ const migration = migrateIfNeeded();
10662
+ if (migration.migrated.length > 0) {
10663
+ for (const dir of migration.migrated) {
10664
+ p4.log.info(`Migrated \u2192 ~/.aman-agent/${dir}/`);
10665
+ }
10666
+ }
10667
+ process.env.ACORE_HOME = identityDir();
10668
+ process.env.ARULES_HOME = rulesDir();
10669
+ process.env.AMEM_DIR = memoryDir();
10137
10670
  const isFirstRun = bootstrapEcosystem();
10138
10671
  if (!hasUserIdentity()) {
10139
10672
  s.stop("Ecosystem loaded");
@@ -10251,19 +10784,18 @@ program.command("init").description("Set up your AI companion with a guided wiza
10251
10784
  });
10252
10785
  if (p4.isCancel(preset)) process.exit(0);
10253
10786
  const result = applyPreset(preset, name || "Aman");
10254
- const home2 = os22.homedir();
10255
- fs23.mkdirSync(path23.join(home2, ".acore"), { recursive: true });
10256
- fs23.writeFileSync(path23.join(home2, ".acore", "core.md"), result.coreMd, "utf-8");
10787
+ fs27.mkdirSync(identityDir(), { recursive: true });
10788
+ fs27.writeFileSync(path28.join(identityDir(), "core.md"), result.coreMd, "utf-8");
10257
10789
  p4.log.success(`Identity created \u2014 ${PRESETS[preset].identity.personality.split(".")[0].toLowerCase()}`);
10258
10790
  if (result.rulesMd) {
10259
- fs23.mkdirSync(path23.join(home2, ".arules"), { recursive: true });
10260
- fs23.writeFileSync(path23.join(home2, ".arules", "rules.md"), result.rulesMd, "utf-8");
10791
+ fs27.mkdirSync(rulesDir(), { recursive: true });
10792
+ fs27.writeFileSync(path28.join(rulesDir(), "rules.md"), result.rulesMd, "utf-8");
10261
10793
  const ruleCount = (result.rulesMd.match(/^- /gm) || []).length;
10262
10794
  p4.log.success(`${ruleCount} rules set`);
10263
10795
  }
10264
10796
  if (result.flowMd) {
10265
- fs23.mkdirSync(path23.join(home2, ".aflow"), { recursive: true });
10266
- fs23.writeFileSync(path23.join(home2, ".aflow", "flow.md"), result.flowMd, "utf-8");
10797
+ fs27.mkdirSync(workflowsDir(), { recursive: true });
10798
+ fs27.writeFileSync(path28.join(workflowsDir(), "flow.md"), result.flowMd, "utf-8");
10267
10799
  const wfCount = (result.flowMd.match(/^## /gm) || []).length;
10268
10800
  p4.log.success(`${wfCount} workflow${wfCount > 1 ? "s" : ""} added`);
10269
10801
  }
@@ -10292,5 +10824,121 @@ program.command("serve").description("Run aman-agent as a local MCP server other
10292
10824
  process.exit(1);
10293
10825
  }
10294
10826
  });
10827
+ program.command("dev [path]").description("Set up project context and start Claude Code").option("--smart", "Use LLM to generate CLAUDE.md").option("--no-launch", "Generate CLAUDE.md only, don't start claude").option("--force", "Regenerate even if CLAUDE.md is fresh").option("--diff", "Show what would change without writing").action(async (projectPath, opts) => {
10828
+ const { runDev: runDev2 } = await Promise.resolve().then(() => (init_dev_command(), dev_command_exports));
10829
+ const { scanStack: scanStack2 } = await Promise.resolve().then(() => (init_stack_detector(), stack_detector_exports));
10830
+ const targetPath = projectPath ?? process.cwd();
10831
+ const stack = scanStack2(targetPath);
10832
+ const stackParts = stack.languages.map((l) => l.charAt(0).toUpperCase() + l.slice(1));
10833
+ if (stack.frameworks.length > 0) {
10834
+ stackParts.push(`(${stack.frameworks.map((f) => f.charAt(0).toUpperCase() + f.slice(1)).join(", ")})`);
10835
+ }
10836
+ if (stack.databases.length > 0) {
10837
+ stackParts.push(...stack.databases.map((d) => d.charAt(0).toUpperCase() + d.slice(1)));
10838
+ }
10839
+ if (stack.infra.length > 0) {
10840
+ stackParts.push(...stack.infra.map((i) => i.charAt(0).toUpperCase() + i.slice(1)));
10841
+ }
10842
+ if (stack.languages.length > 0) {
10843
+ console.log(`
10844
+ ${pc9.cyan("Detected:")} ${stackParts.join(" + ")}`);
10845
+ } else {
10846
+ console.log(`
10847
+ ${pc9.dim("No stack detected \u2014 generating minimal CLAUDE.md")}`);
10848
+ }
10849
+ const result = await runDev2(targetPath, {
10850
+ smart: opts.smart,
10851
+ noLaunch: opts.launch === false,
10852
+ force: opts.force,
10853
+ diff: opts.diff
10854
+ }, stack);
10855
+ if (!result.success) {
10856
+ console.error(` ${pc9.red("Error:")} ${result.error}`);
10857
+ process.exit(1);
10858
+ }
10859
+ if (result.diff) {
10860
+ console.log(`
10861
+ ${result.diff}`);
10862
+ return;
10863
+ }
10864
+ if (result.generated) {
10865
+ const mode = opts.smart ? "smart" : "template";
10866
+ const memCount = result.context?.metadata.memoriesUsed ?? 0;
10867
+ console.log(` ${pc9.cyan("Recalled:")} ${memCount} memories`);
10868
+ console.log(` ${pc9.green("\u2713")} CLAUDE.md written (${mode} mode)
10869
+ `);
10870
+ } else if (result.skippedReason === "fresh") {
10871
+ console.log(` ${pc9.green("\u2713")} CLAUDE.md is up to date
10872
+ `);
10873
+ }
10874
+ if (opts.launch !== false && !opts.diff) {
10875
+ const { execFileSync: execFileSync4 } = await import("child_process");
10876
+ try {
10877
+ execFileSync4("which", ["claude"], { stdio: "ignore" });
10878
+ } catch {
10879
+ console.log(` ${pc9.yellow("Claude Code not found.")} Install: npm install -g @anthropic-ai/claude-code`);
10880
+ process.exit(1);
10881
+ }
10882
+ console.log(` ${pc9.cyan("Launching Claude Code...")}
10883
+ `);
10884
+ execFileSync4("claude", [], { cwd: targetPath, stdio: "inherit" });
10885
+ }
10886
+ });
10887
+ program.command("setup").description("Run the full configuration wizard (provider, identity, presets)").action(async () => {
10888
+ p4.intro(pc9.bold("aman agent setup") + pc9.dim(" \u2014 full configuration wizard"));
10889
+ const reconfigPath = path28.join(homeDir(), ".reconfig");
10890
+ fs27.mkdirSync(homeDir(), { recursive: true });
10891
+ fs27.writeFileSync(reconfigPath, "", "utf-8");
10892
+ p4.log.info("Configuration reset. Restart aman-agent to complete setup.");
10893
+ });
10894
+ program.command("update").description("Update aman-agent to the latest version").action(async () => {
10895
+ const { execFileSync: execFileSync4 } = await import("child_process");
10896
+ const isVendored = process.execPath.includes(path28.join(".aman-agent", "node"));
10897
+ if (isVendored) {
10898
+ const npmPath = path28.join(homeDir(), "node", "bin", "npm");
10899
+ console.log("Updating aman-agent...");
10900
+ try {
10901
+ execFileSync4(npmPath, ["install", "-g", "@aman_asmuei/aman-agent@latest"], {
10902
+ stdio: "inherit",
10903
+ env: { ...process.env, PREFIX: homeDir() }
10904
+ });
10905
+ console.log("\u2713 Updated successfully.");
10906
+ } catch {
10907
+ console.error("Update failed. Try manually: npm install -g @aman_asmuei/aman-agent@latest");
10908
+ process.exit(1);
10909
+ }
10910
+ } else {
10911
+ console.log("Updating via npm...");
10912
+ try {
10913
+ execFileSync4("npm", ["install", "-g", "@aman_asmuei/aman-agent@latest"], {
10914
+ stdio: "inherit"
10915
+ });
10916
+ console.log("\u2713 Updated successfully.");
10917
+ } catch {
10918
+ console.error("Update failed. Try manually: npm install -g @aman_asmuei/aman-agent@latest");
10919
+ process.exit(1);
10920
+ }
10921
+ }
10922
+ });
10923
+ program.command("uninstall").description("Remove aman-agent and all its data").action(async () => {
10924
+ const home2 = homeDir();
10925
+ if (!process.stdin.isTTY) {
10926
+ fs27.rmSync(home2, { recursive: true, force: true });
10927
+ console.log("\u2713 Removed " + home2);
10928
+ return;
10929
+ }
10930
+ const confirm3 = await p4.confirm({
10931
+ message: `This will delete ${home2} and all your data (memory, identity, config). Continue?`
10932
+ });
10933
+ if (!confirm3 || p4.isCancel(confirm3)) {
10934
+ console.log("Cancelled.");
10935
+ return;
10936
+ }
10937
+ fs27.rmSync(home2, { recursive: true, force: true });
10938
+ console.log("\u2713 Removed " + home2);
10939
+ console.log("");
10940
+ console.log("To complete uninstall, remove the PATH line from your shell config:");
10941
+ console.log(' Remove: export PATH="$HOME/.aman-agent/bin:$PATH"');
10942
+ });
10295
10943
  program.parse();
10296
10944
  //# sourceMappingURL=index.js.map