@aman_asmuei/aman-agent 0.17.1 → 0.17.2
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 +133 -94
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -232,7 +232,7 @@ function toAnthropicMessages(messages) {
|
|
|
232
232
|
function createAnthropicClient(apiKey, model) {
|
|
233
233
|
const client = new Anthropic({ apiKey });
|
|
234
234
|
return {
|
|
235
|
-
async chat(systemPrompt, messages, onChunk, tools) {
|
|
235
|
+
async chat(systemPrompt, messages, onChunk, tools, options) {
|
|
236
236
|
const anthropicMessages = toAnthropicMessages(messages);
|
|
237
237
|
const hasTools = tools && tools.length > 0;
|
|
238
238
|
try {
|
|
@@ -242,7 +242,7 @@ function createAnthropicClient(apiKey, model) {
|
|
|
242
242
|
let currentBlockIndex = -1;
|
|
243
243
|
const createParams = {
|
|
244
244
|
model,
|
|
245
|
-
max_tokens: 8192,
|
|
245
|
+
max_tokens: options?.maxOutputTokens ?? 8192,
|
|
246
246
|
system: systemPrompt,
|
|
247
247
|
messages: anthropicMessages,
|
|
248
248
|
stream: true
|
|
@@ -330,7 +330,9 @@ function createAnthropicClient(apiKey, model) {
|
|
|
330
330
|
|
|
331
331
|
// src/llm/openai.ts
|
|
332
332
|
import OpenAI from "openai";
|
|
333
|
-
|
|
333
|
+
|
|
334
|
+
// src/llm/openai-compat.ts
|
|
335
|
+
function toOpenAICompatibleMessages(systemPrompt, messages) {
|
|
334
336
|
const result = [
|
|
335
337
|
{ role: "system", content: systemPrompt }
|
|
336
338
|
];
|
|
@@ -398,18 +400,20 @@ function toOpenAIMessages(systemPrompt, messages) {
|
|
|
398
400
|
}
|
|
399
401
|
return result;
|
|
400
402
|
}
|
|
403
|
+
|
|
404
|
+
// src/llm/openai.ts
|
|
401
405
|
function createOpenAIClient(apiKey, model) {
|
|
402
406
|
const client = new OpenAI({ apiKey });
|
|
403
407
|
return {
|
|
404
|
-
async chat(systemPrompt, messages, onChunk, tools) {
|
|
405
|
-
const openaiMessages =
|
|
408
|
+
async chat(systemPrompt, messages, onChunk, tools, options) {
|
|
409
|
+
const openaiMessages = toOpenAICompatibleMessages(systemPrompt, messages);
|
|
406
410
|
const hasTools = tools && tools.length > 0;
|
|
407
411
|
try {
|
|
408
412
|
let fullText = "";
|
|
409
413
|
const toolCallAccumulators = /* @__PURE__ */ new Map();
|
|
410
414
|
const createParams = {
|
|
411
415
|
model,
|
|
412
|
-
max_tokens: 8192,
|
|
416
|
+
max_tokens: options?.maxOutputTokens ?? 8192,
|
|
413
417
|
messages: openaiMessages,
|
|
414
418
|
stream: true
|
|
415
419
|
};
|
|
@@ -495,74 +499,6 @@ function createOpenAIClient(apiKey, model) {
|
|
|
495
499
|
|
|
496
500
|
// src/llm/ollama.ts
|
|
497
501
|
import OpenAI2 from "openai";
|
|
498
|
-
function toOllamaMessages(systemPrompt, messages) {
|
|
499
|
-
const result = [
|
|
500
|
-
{ role: "system", content: systemPrompt }
|
|
501
|
-
];
|
|
502
|
-
for (const m of messages) {
|
|
503
|
-
if (typeof m.content === "string") {
|
|
504
|
-
result.push({
|
|
505
|
-
role: m.role,
|
|
506
|
-
content: m.content
|
|
507
|
-
});
|
|
508
|
-
} else if (m.role === "assistant") {
|
|
509
|
-
const textParts = m.content.filter((b) => b.type === "text");
|
|
510
|
-
const toolUseParts = m.content.filter((b) => b.type === "tool_use");
|
|
511
|
-
const text2 = textParts.map((b) => "text" in b ? b.text : "").join("");
|
|
512
|
-
if (toolUseParts.length > 0) {
|
|
513
|
-
result.push({
|
|
514
|
-
role: "assistant",
|
|
515
|
-
content: text2 || null,
|
|
516
|
-
tool_calls: toolUseParts.map((b) => ({
|
|
517
|
-
id: "id" in b ? b.id : "",
|
|
518
|
-
type: "function",
|
|
519
|
-
function: {
|
|
520
|
-
name: "name" in b ? b.name : "",
|
|
521
|
-
arguments: JSON.stringify("input" in b ? b.input : {})
|
|
522
|
-
}
|
|
523
|
-
}))
|
|
524
|
-
});
|
|
525
|
-
} else {
|
|
526
|
-
result.push({ role: "assistant", content: text2 });
|
|
527
|
-
}
|
|
528
|
-
} else if (m.role === "user") {
|
|
529
|
-
const toolResults = m.content.filter((b) => b.type === "tool_result");
|
|
530
|
-
if (toolResults.length > 0) {
|
|
531
|
-
for (const tr of toolResults) {
|
|
532
|
-
if (tr.type === "tool_result") {
|
|
533
|
-
result.push({
|
|
534
|
-
role: "tool",
|
|
535
|
-
tool_call_id: tr.tool_use_id,
|
|
536
|
-
content: tr.content
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
} else {
|
|
541
|
-
const hasImages = m.content.some((b) => b.type === "image");
|
|
542
|
-
if (hasImages) {
|
|
543
|
-
const parts = [];
|
|
544
|
-
for (const b of m.content) {
|
|
545
|
-
if (b.type === "text") {
|
|
546
|
-
parts.push({ type: "text", text: b.text });
|
|
547
|
-
} else if (b.type === "image") {
|
|
548
|
-
parts.push({
|
|
549
|
-
type: "image_url",
|
|
550
|
-
image_url: {
|
|
551
|
-
url: `data:${b.source.media_type};base64,${b.source.data}`
|
|
552
|
-
}
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
result.push({ role: "user", content: parts });
|
|
557
|
-
} else {
|
|
558
|
-
const text2 = m.content.map((b) => "text" in b ? b.text : "").join("");
|
|
559
|
-
result.push({ role: "user", content: text2 });
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
return result;
|
|
565
|
-
}
|
|
566
502
|
function createOllamaClient(model, baseURL) {
|
|
567
503
|
const client = new OpenAI2({
|
|
568
504
|
baseURL: baseURL || "http://localhost:11434/v1",
|
|
@@ -570,15 +506,15 @@ function createOllamaClient(model, baseURL) {
|
|
|
570
506
|
// Ollama doesn't require a real key
|
|
571
507
|
});
|
|
572
508
|
return {
|
|
573
|
-
async chat(systemPrompt, messages, onChunk, tools) {
|
|
574
|
-
const ollamaMessages =
|
|
509
|
+
async chat(systemPrompt, messages, onChunk, tools, options) {
|
|
510
|
+
const ollamaMessages = toOpenAICompatibleMessages(systemPrompt, messages);
|
|
575
511
|
const hasTools = tools && tools.length > 0;
|
|
576
512
|
try {
|
|
577
513
|
let fullText = "";
|
|
578
514
|
const toolCallAccumulators = /* @__PURE__ */ new Map();
|
|
579
515
|
const createParams = {
|
|
580
516
|
model,
|
|
581
|
-
max_tokens:
|
|
517
|
+
max_tokens: options?.maxOutputTokens ?? 4096,
|
|
582
518
|
messages: ollamaMessages,
|
|
583
519
|
stream: true
|
|
584
520
|
};
|
|
@@ -730,12 +666,18 @@ async function withRetry(fn, options) {
|
|
|
730
666
|
}
|
|
731
667
|
|
|
732
668
|
// src/mcp/client.ts
|
|
669
|
+
var TOOL_CALL_TIMEOUT_MS = 3e4;
|
|
733
670
|
var McpManager = class {
|
|
734
671
|
connections = [];
|
|
735
672
|
tools = [];
|
|
736
|
-
async connect(name, command, args) {
|
|
673
|
+
async connect(name, command, args, env) {
|
|
737
674
|
try {
|
|
738
|
-
const transport = new StdioClientTransport({
|
|
675
|
+
const transport = new StdioClientTransport({
|
|
676
|
+
command,
|
|
677
|
+
args,
|
|
678
|
+
stderr: "pipe",
|
|
679
|
+
env: env ? env : void 0
|
|
680
|
+
});
|
|
739
681
|
const client = new Client({
|
|
740
682
|
name: `aman-agent-${name}`,
|
|
741
683
|
version: "0.1.0"
|
|
@@ -746,9 +688,16 @@ var McpManager = class {
|
|
|
746
688
|
log.debug("mcp", `[${name} stderr] ${chunk.toString().trim()}`);
|
|
747
689
|
});
|
|
748
690
|
}
|
|
749
|
-
this.connections.push({ name, client, transport });
|
|
691
|
+
this.connections.push({ name, client, transport, connectParams: { command, args, env } });
|
|
750
692
|
const toolsResult = await client.listTools();
|
|
751
693
|
for (const tool of toolsResult.tools) {
|
|
694
|
+
const existing = this.tools.find((t) => t.name === tool.name);
|
|
695
|
+
if (existing) {
|
|
696
|
+
log.warn(
|
|
697
|
+
"mcp",
|
|
698
|
+
`Warning: tool "${tool.name}" from server "${name}" shadows existing tool from "${existing.serverName}"`
|
|
699
|
+
);
|
|
700
|
+
}
|
|
752
701
|
this.tools.push({
|
|
753
702
|
name: tool.name,
|
|
754
703
|
description: tool.description || "",
|
|
@@ -771,7 +720,15 @@ var McpManager = class {
|
|
|
771
720
|
if (!conn) return `Error: server ${tool.serverName} not connected`;
|
|
772
721
|
try {
|
|
773
722
|
const result = await withRetry(
|
|
774
|
-
() =>
|
|
723
|
+
() => Promise.race([
|
|
724
|
+
conn.client.callTool({ name: toolName, arguments: args }),
|
|
725
|
+
new Promise(
|
|
726
|
+
(_, reject) => setTimeout(
|
|
727
|
+
() => reject(new Error(`Tool ${toolName} timed out after 30s`)),
|
|
728
|
+
TOOL_CALL_TIMEOUT_MS
|
|
729
|
+
)
|
|
730
|
+
)
|
|
731
|
+
]),
|
|
775
732
|
{ maxAttempts: 2, baseDelay: 500, retryable: (err) => err.message.includes("ETIMEDOUT") || err.message.includes("timeout") }
|
|
776
733
|
);
|
|
777
734
|
if (result.content && Array.isArray(result.content)) {
|
|
@@ -782,6 +739,23 @@ var McpManager = class {
|
|
|
782
739
|
return `Error calling ${toolName}: ${error instanceof Error ? error.message : String(error)}`;
|
|
783
740
|
}
|
|
784
741
|
}
|
|
742
|
+
async reconnect(name) {
|
|
743
|
+
const connIndex = this.connections.findIndex((c) => c.name === name);
|
|
744
|
+
if (connIndex === -1) {
|
|
745
|
+
log.error("mcp", `Cannot reconnect: no connection found for "${name}"`);
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
const conn = this.connections[connIndex];
|
|
749
|
+
const { command, args, env } = conn.connectParams;
|
|
750
|
+
try {
|
|
751
|
+
await conn.client.close();
|
|
752
|
+
} catch (err) {
|
|
753
|
+
log.debug("mcp", `Error closing old connection for ${name}`, err);
|
|
754
|
+
}
|
|
755
|
+
this.connections.splice(connIndex, 1);
|
|
756
|
+
this.tools = this.tools.filter((t) => t.serverName !== name);
|
|
757
|
+
await this.connect(name, command, args, env);
|
|
758
|
+
}
|
|
785
759
|
async disconnect() {
|
|
786
760
|
for (const conn of this.connections) {
|
|
787
761
|
try {
|
|
@@ -893,7 +867,27 @@ async function initMemory(project) {
|
|
|
893
867
|
const amemDir = process.env.AMEM_DIR ?? path5.join(os5.homedir(), ".amem");
|
|
894
868
|
if (!fs5.existsSync(amemDir)) fs5.mkdirSync(amemDir, { recursive: true });
|
|
895
869
|
const dbPath = process.env.AMEM_DB ?? path5.join(amemDir, "memory.db");
|
|
896
|
-
|
|
870
|
+
try {
|
|
871
|
+
db = createDatabase(dbPath);
|
|
872
|
+
} catch (err) {
|
|
873
|
+
const backupPath = `${dbPath}.corrupt.${Date.now()}`;
|
|
874
|
+
try {
|
|
875
|
+
if (fs5.existsSync(dbPath)) {
|
|
876
|
+
fs5.renameSync(dbPath, backupPath);
|
|
877
|
+
if (fs5.existsSync(`${dbPath}-wal`)) fs5.unlinkSync(`${dbPath}-wal`);
|
|
878
|
+
if (fs5.existsSync(`${dbPath}-shm`)) fs5.unlinkSync(`${dbPath}-shm`);
|
|
879
|
+
console.error(`[amem] Database corrupted \u2014 backed up to ${backupPath}`);
|
|
880
|
+
console.error("[amem] Creating fresh database. Previous memories are in the backup file.");
|
|
881
|
+
db = createDatabase(dbPath);
|
|
882
|
+
} else {
|
|
883
|
+
throw err;
|
|
884
|
+
}
|
|
885
|
+
} catch {
|
|
886
|
+
console.error(`[amem] Failed to initialize memory: ${err instanceof Error ? err.message : String(err)}`);
|
|
887
|
+
console.error(`[amem] Try deleting ${amemDir} to reset: rm -rf ${amemDir}`);
|
|
888
|
+
throw err;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
897
891
|
currentProject = project ?? "global";
|
|
898
892
|
preloadEmbeddings();
|
|
899
893
|
setTimeout(() => {
|
|
@@ -974,12 +968,19 @@ async function memoryForget(opts) {
|
|
|
974
968
|
}
|
|
975
969
|
return { deleted: 0, message: "Provide an id, type, or query to forget." };
|
|
976
970
|
}
|
|
971
|
+
var memoryConfig = {};
|
|
972
|
+
function setMemoryConfig(config) {
|
|
973
|
+
memoryConfig = config;
|
|
974
|
+
}
|
|
975
|
+
function getMaxRecallTokens() {
|
|
976
|
+
return memoryConfig.maxRecallTokens ?? 1500;
|
|
977
|
+
}
|
|
977
978
|
function memoryConsolidate(dryRun = false) {
|
|
978
979
|
return consolidateMemories(getDb(), cosineSimilarity, {
|
|
979
980
|
dryRun,
|
|
980
|
-
maxStaleDays: 90,
|
|
981
|
-
minConfidence: 0.3,
|
|
982
|
-
minAccessCount: 0
|
|
981
|
+
maxStaleDays: memoryConfig.maxStaleDays ?? 90,
|
|
982
|
+
minConfidence: memoryConfig.minConfidence ?? 0.3,
|
|
983
|
+
minAccessCount: memoryConfig.minAccessCount ?? 0
|
|
983
984
|
});
|
|
984
985
|
}
|
|
985
986
|
function isMemoryInitialized() {
|
|
@@ -2136,7 +2137,7 @@ async function handleMemoryCommand(action, args, ctx) {
|
|
|
2136
2137
|
}
|
|
2137
2138
|
try {
|
|
2138
2139
|
if (args[0] === "--type" && args[1]) {
|
|
2139
|
-
const result2 = await memoryForget({
|
|
2140
|
+
const result2 = await memoryForget({ type: args[1] });
|
|
2140
2141
|
return { handled: true, output: result2.deleted > 0 ? pc3.green(result2.message) : pc3.dim(result2.message) };
|
|
2141
2142
|
}
|
|
2142
2143
|
const result = await memoryForget({ query: args.join(" ") });
|
|
@@ -2378,6 +2379,10 @@ function handleHelp() {
|
|
|
2378
2379
|
` ${pc3.cyan("/debug")} Show debug log`,
|
|
2379
2380
|
` ${pc3.cyan("/save")} Save conversation to memory`,
|
|
2380
2381
|
` ${pc3.cyan("/model")} Show current LLM model`,
|
|
2382
|
+
` ${pc3.cyan("/plan")} Manage multi-step plans`,
|
|
2383
|
+
` ${pc3.cyan("/profile")} Switch agent profiles`,
|
|
2384
|
+
` ${pc3.cyan("/delegate")} Delegate tasks to sub-agents`,
|
|
2385
|
+
` ${pc3.cyan("/team")} Manage agent teams`,
|
|
2381
2386
|
` ${pc3.cyan("/update")} Check for updates`,
|
|
2382
2387
|
` ${pc3.cyan("/reset")} Full reset [all|memory|config|identity|rules]`,
|
|
2383
2388
|
` ${pc3.cyan("/clear")} Clear conversation history`,
|
|
@@ -2443,7 +2448,7 @@ function handleReset(action) {
|
|
|
2443
2448
|
function handleUpdate() {
|
|
2444
2449
|
try {
|
|
2445
2450
|
const current = execFileSync("npm", ["view", "@aman_asmuei/aman-agent", "version"], { encoding: "utf-8" }).trim();
|
|
2446
|
-
const local =
|
|
2451
|
+
const local = true ? "0.17.2" : "unknown";
|
|
2447
2452
|
if (current === local) {
|
|
2448
2453
|
return { handled: true, output: `${pc3.green("Up to date")} \u2014 v${local}` };
|
|
2449
2454
|
}
|
|
@@ -4017,8 +4022,8 @@ Rules:
|
|
|
4017
4022
|
- Be conservative \u2014 90% of turns produce nothing worth storing
|
|
4018
4023
|
- Return ONLY the JSON array, no other text`;
|
|
4019
4024
|
function shouldExtract(assistantResponse, turnsSinceLastExtraction, lastExtractionCount) {
|
|
4020
|
-
if (lastExtractionCount > 0) return true;
|
|
4021
4025
|
if (assistantResponse.length < MIN_RESPONSE_LENGTH) return false;
|
|
4026
|
+
if (lastExtractionCount > 0 && turnsSinceLastExtraction >= 1) return true;
|
|
4022
4027
|
if (turnsSinceLastExtraction < MIN_TURNS_BETWEEN_EMPTY) return false;
|
|
4023
4028
|
return true;
|
|
4024
4029
|
}
|
|
@@ -4333,13 +4338,20 @@ async function recallForMessage(input) {
|
|
|
4333
4338
|
return null;
|
|
4334
4339
|
}
|
|
4335
4340
|
const tokenEstimate = result.tokenEstimate ?? Math.round(result.text.split(/\s+/).filter(Boolean).length * 1.3);
|
|
4341
|
+
const MAX_MEMORY_TOKENS = getMaxRecallTokens();
|
|
4342
|
+
let memoryText = result.text;
|
|
4343
|
+
if (tokenEstimate > MAX_MEMORY_TOKENS) {
|
|
4344
|
+
const maxChars = MAX_MEMORY_TOKENS * 4;
|
|
4345
|
+
memoryText = memoryText.slice(0, maxChars) + "\n[... memory truncated to fit token budget]";
|
|
4346
|
+
log.debug("agent", `memory recall truncated from ~${tokenEstimate} to ~${MAX_MEMORY_TOKENS} tokens`);
|
|
4347
|
+
}
|
|
4336
4348
|
return {
|
|
4337
4349
|
text: `
|
|
4338
4350
|
|
|
4339
4351
|
<relevant-memories>
|
|
4340
|
-
${
|
|
4352
|
+
${memoryText}
|
|
4341
4353
|
</relevant-memories>`,
|
|
4342
|
-
tokenEstimate
|
|
4354
|
+
tokenEstimate: Math.min(tokenEstimate, MAX_MEMORY_TOKENS)
|
|
4343
4355
|
};
|
|
4344
4356
|
} catch (err) {
|
|
4345
4357
|
log.debug("agent", "memory recall failed", err);
|
|
@@ -4395,7 +4407,7 @@ async function runAgent(client, systemPrompt, aiName, model, tools, mcpManager,
|
|
|
4395
4407
|
shownHints: loadShownHints(),
|
|
4396
4408
|
hintShownThisSession: false
|
|
4397
4409
|
};
|
|
4398
|
-
const isRetryable2 = (err) => err.message.includes("Rate limit") || err.message.includes("rate limit") || err.message.includes("ECONNRESET") || err.message.includes("ETIMEDOUT") || err.message.includes("fetch failed");
|
|
4410
|
+
const isRetryable2 = (err) => err.message.includes("Rate limit") || err.message.includes("rate limit") || err.message.includes("ECONNRESET") || err.message.includes("ETIMEDOUT") || err.message.includes("fetch failed") || err.message.includes("socket hang up") || err.message.includes("network socket disconnected") || err.message.includes("ENOTFOUND") || err.message.includes("EAI_AGAIN");
|
|
4399
4411
|
let responseBuffer = "";
|
|
4400
4412
|
const onChunkHandler = (chunk) => {
|
|
4401
4413
|
if (chunk.type === "text" && chunk.text) {
|
|
@@ -4813,7 +4825,18 @@ ${converted}
|
|
|
4813
4825
|
{ maxAttempts: 3, baseDelay: 1e3, retryable: isRetryable2 }
|
|
4814
4826
|
);
|
|
4815
4827
|
messages.push(response.message);
|
|
4828
|
+
const MAX_TOOL_TURNS = 20;
|
|
4829
|
+
let toolTurnCount = 0;
|
|
4816
4830
|
while (response.toolUses.length > 0 && mcpManager) {
|
|
4831
|
+
toolTurnCount++;
|
|
4832
|
+
if (toolTurnCount > MAX_TOOL_TURNS) {
|
|
4833
|
+
messages.push({
|
|
4834
|
+
role: "assistant",
|
|
4835
|
+
content: "Tool execution limit reached (20). Breaking to prevent infinite loop."
|
|
4836
|
+
});
|
|
4837
|
+
console.log(pc6.yellow("\n Tool execution limit reached (20). Breaking to prevent infinite loop."));
|
|
4838
|
+
break;
|
|
4839
|
+
}
|
|
4817
4840
|
const toolResults = await Promise.all(
|
|
4818
4841
|
response.toolUses.map(async (toolUse) => {
|
|
4819
4842
|
if (hooksConfig) {
|
|
@@ -5128,10 +5151,22 @@ function bootstrapEcosystem() {
|
|
|
5128
5151
|
"- Respect the user's preferences stored in memory"
|
|
5129
5152
|
].join("\n"), "utf-8");
|
|
5130
5153
|
}
|
|
5154
|
+
const flowDir = path14.join(home2, ".aflow");
|
|
5155
|
+
const flowPath = path14.join(flowDir, "flow.md");
|
|
5156
|
+
if (!fs14.existsSync(flowPath)) {
|
|
5157
|
+
fs14.mkdirSync(flowDir, { recursive: true });
|
|
5158
|
+
fs14.writeFileSync(flowPath, "# Workflows\n\n_No workflows defined yet. Use /workflows add to create one._\n", "utf-8");
|
|
5159
|
+
}
|
|
5160
|
+
const skillDir = path14.join(home2, ".askill");
|
|
5161
|
+
const skillPath = path14.join(skillDir, "skills.md");
|
|
5162
|
+
if (!fs14.existsSync(skillPath)) {
|
|
5163
|
+
fs14.mkdirSync(skillDir, { recursive: true });
|
|
5164
|
+
fs14.writeFileSync(skillPath, "# Skills\n\n_No skills installed yet. Use /skills install to add domain expertise._\n", "utf-8");
|
|
5165
|
+
}
|
|
5131
5166
|
return true;
|
|
5132
5167
|
}
|
|
5133
5168
|
var program = new Command();
|
|
5134
|
-
program.name("aman-agent").description("Your AI companion, running locally").version("0.17.
|
|
5169
|
+
program.name("aman-agent").description("Your AI companion, running locally").version("0.17.2").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) => {
|
|
5135
5170
|
p2.intro(pc7.bold("aman agent") + pc7.dim(" \u2014 your AI companion"));
|
|
5136
5171
|
let config = loadConfig();
|
|
5137
5172
|
if (!config) {
|
|
@@ -5258,6 +5293,7 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
5258
5293
|
}
|
|
5259
5294
|
}
|
|
5260
5295
|
const aiName = getProfileAiName(profile);
|
|
5296
|
+
if (config.memory) setMemoryConfig(config.memory);
|
|
5261
5297
|
try {
|
|
5262
5298
|
await initMemory();
|
|
5263
5299
|
} catch (err) {
|
|
@@ -5281,13 +5317,16 @@ program.name("aman-agent").description("Your AI companion, running locally").ver
|
|
|
5281
5317
|
const mcpManager = new McpManager();
|
|
5282
5318
|
const mcpSpinner = p2.spinner();
|
|
5283
5319
|
mcpSpinner.start("Connecting to MCP servers");
|
|
5284
|
-
|
|
5320
|
+
const connections = [
|
|
5321
|
+
mcpManager.connect("aman", "npx", ["-y", "@aman_asmuei/aman-mcp"])
|
|
5322
|
+
];
|
|
5285
5323
|
if (config.mcpServers) {
|
|
5286
5324
|
for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
|
|
5287
5325
|
if (name === "aman" || name === "amem") continue;
|
|
5288
|
-
|
|
5326
|
+
connections.push(mcpManager.connect(name, serverConfig.command, serverConfig.args, serverConfig.env));
|
|
5289
5327
|
}
|
|
5290
5328
|
}
|
|
5329
|
+
await Promise.all(connections);
|
|
5291
5330
|
const mcpTools = mcpManager.getTools();
|
|
5292
5331
|
mcpSpinner.stop("MCP connected");
|
|
5293
5332
|
if (mcpTools.length > 0) {
|