@defai.digital/automatosx 12.4.1 → 12.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -1
- package/dist/index.js +1952 -272
- package/dist/mcp/index.js +282 -11
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -8727,7 +8727,7 @@ var PRECOMPILED_CONFIG = {
|
|
|
8727
8727
|
"enableFreeTierPrioritization": true,
|
|
8728
8728
|
"enableWorkloadAwareRouting": true
|
|
8729
8729
|
},
|
|
8730
|
-
"version": "12.
|
|
8730
|
+
"version": "12.5.1"
|
|
8731
8731
|
};
|
|
8732
8732
|
|
|
8733
8733
|
// src/core/config/schemas.ts
|
|
@@ -20348,6 +20348,232 @@ ${context.task}`;
|
|
|
20348
20348
|
}
|
|
20349
20349
|
};
|
|
20350
20350
|
|
|
20351
|
+
// src/agents/agent-selector.ts
|
|
20352
|
+
init_esm_shims();
|
|
20353
|
+
init_logger();
|
|
20354
|
+
function scoreAgent(task, profile) {
|
|
20355
|
+
let score = 0;
|
|
20356
|
+
const taskLower = task.toLowerCase();
|
|
20357
|
+
if (profile.selectionMetadata?.primaryIntents) {
|
|
20358
|
+
for (const intent of profile.selectionMetadata.primaryIntents) {
|
|
20359
|
+
const intentKeywords = intent.toLowerCase().split(/\s+/);
|
|
20360
|
+
const matchedKeywords = intentKeywords.filter(
|
|
20361
|
+
(keyword) => taskLower.includes(keyword) && keyword.length > 3
|
|
20362
|
+
);
|
|
20363
|
+
if (matchedKeywords.length >= 2) {
|
|
20364
|
+
score += 10;
|
|
20365
|
+
} else if (matchedKeywords.length === 1) {
|
|
20366
|
+
score += 5;
|
|
20367
|
+
}
|
|
20368
|
+
}
|
|
20369
|
+
}
|
|
20370
|
+
if (profile.selectionMetadata?.secondarySignals) {
|
|
20371
|
+
for (const signal of profile.selectionMetadata.secondarySignals) {
|
|
20372
|
+
if (taskLower.includes(signal.toLowerCase())) {
|
|
20373
|
+
score += 5;
|
|
20374
|
+
}
|
|
20375
|
+
}
|
|
20376
|
+
}
|
|
20377
|
+
if (profile.selectionMetadata?.negativeIntents) {
|
|
20378
|
+
for (const negative of profile.selectionMetadata.negativeIntents) {
|
|
20379
|
+
const keywords = negative.split("(")[0]?.toLowerCase() || "";
|
|
20380
|
+
const negativeKeywords = keywords.split(/\s+/).filter((k) => k.length > 3);
|
|
20381
|
+
const matchedNegative = negativeKeywords.filter(
|
|
20382
|
+
(keyword) => taskLower.includes(keyword)
|
|
20383
|
+
);
|
|
20384
|
+
if (matchedNegative.length >= 2) {
|
|
20385
|
+
score -= 20;
|
|
20386
|
+
}
|
|
20387
|
+
}
|
|
20388
|
+
}
|
|
20389
|
+
if (profile.selectionMetadata?.redirectWhen) {
|
|
20390
|
+
for (const rule of profile.selectionMetadata.redirectWhen) {
|
|
20391
|
+
try {
|
|
20392
|
+
const regex = new RegExp(rule.phrase, "i");
|
|
20393
|
+
if (regex.test(task)) {
|
|
20394
|
+
score -= 15;
|
|
20395
|
+
}
|
|
20396
|
+
} catch (error) {
|
|
20397
|
+
logger.debug("Invalid regex pattern in redirectWhen rule", {
|
|
20398
|
+
pattern: rule.phrase,
|
|
20399
|
+
error: error instanceof Error ? error.message : String(error)
|
|
20400
|
+
});
|
|
20401
|
+
}
|
|
20402
|
+
}
|
|
20403
|
+
}
|
|
20404
|
+
if (profile.abilitySelection?.taskBased) {
|
|
20405
|
+
for (const keyword of Object.keys(profile.abilitySelection.taskBased)) {
|
|
20406
|
+
if (taskLower.includes(keyword.toLowerCase())) {
|
|
20407
|
+
score += 3;
|
|
20408
|
+
}
|
|
20409
|
+
}
|
|
20410
|
+
}
|
|
20411
|
+
return Math.max(0, score);
|
|
20412
|
+
}
|
|
20413
|
+
function buildRationale(task, profile) {
|
|
20414
|
+
const rationale = [];
|
|
20415
|
+
const taskLower = task.toLowerCase();
|
|
20416
|
+
if (profile.selectionMetadata?.primaryIntents) {
|
|
20417
|
+
const matchedIntents = profile.selectionMetadata.primaryIntents.filter((intent) => {
|
|
20418
|
+
const keywords = intent.toLowerCase().split(/\s+/);
|
|
20419
|
+
return keywords.some((k) => taskLower.includes(k) && k.length > 3);
|
|
20420
|
+
});
|
|
20421
|
+
if (matchedIntents.length > 0) {
|
|
20422
|
+
rationale.push(`Matches: ${matchedIntents.slice(0, 2).join(", ")}`);
|
|
20423
|
+
}
|
|
20424
|
+
}
|
|
20425
|
+
if (profile.selectionMetadata?.secondarySignals) {
|
|
20426
|
+
const matchedSignals = profile.selectionMetadata.secondarySignals.filter(
|
|
20427
|
+
(signal) => taskLower.includes(signal.toLowerCase())
|
|
20428
|
+
);
|
|
20429
|
+
if (matchedSignals.length > 0) {
|
|
20430
|
+
rationale.push(`Keywords: ${matchedSignals.slice(0, 3).join(", ")}`);
|
|
20431
|
+
}
|
|
20432
|
+
}
|
|
20433
|
+
if (profile.abilitySelection?.taskBased) {
|
|
20434
|
+
const matchedAbilities = Object.keys(profile.abilitySelection.taskBased).filter(
|
|
20435
|
+
(keyword) => taskLower.includes(keyword.toLowerCase())
|
|
20436
|
+
);
|
|
20437
|
+
if (matchedAbilities.length > 0) {
|
|
20438
|
+
rationale.push(`Abilities: ${matchedAbilities.slice(0, 2).join(", ")}`);
|
|
20439
|
+
}
|
|
20440
|
+
}
|
|
20441
|
+
if (rationale.length === 0) {
|
|
20442
|
+
rationale.push("General capability match");
|
|
20443
|
+
}
|
|
20444
|
+
return rationale;
|
|
20445
|
+
}
|
|
20446
|
+
function getConfidence(score) {
|
|
20447
|
+
if (score >= 30) return "high";
|
|
20448
|
+
if (score >= 15) return "medium";
|
|
20449
|
+
return "low";
|
|
20450
|
+
}
|
|
20451
|
+
var MIN_SELECTION_SCORE = 5;
|
|
20452
|
+
var FALLBACK_AGENT = "standard";
|
|
20453
|
+
var AgentSelector = class {
|
|
20454
|
+
profileLoader;
|
|
20455
|
+
constructor(profileLoader) {
|
|
20456
|
+
this.profileLoader = profileLoader;
|
|
20457
|
+
}
|
|
20458
|
+
/**
|
|
20459
|
+
* Select the best agent for a task
|
|
20460
|
+
*
|
|
20461
|
+
* @param task - Task description
|
|
20462
|
+
* @returns Selection result with agent, score, confidence, and rationale
|
|
20463
|
+
*/
|
|
20464
|
+
async selectAgent(task) {
|
|
20465
|
+
logger.debug("[AgentSelector] Selecting agent for task", {
|
|
20466
|
+
taskPreview: task.substring(0, 100)
|
|
20467
|
+
});
|
|
20468
|
+
const agentNames = await this.profileLoader.listProfiles();
|
|
20469
|
+
if (agentNames.length === 0) {
|
|
20470
|
+
logger.warn("[AgentSelector] No agents found, using fallback");
|
|
20471
|
+
return this.createFallbackResult(task);
|
|
20472
|
+
}
|
|
20473
|
+
const profileResults = await Promise.all(
|
|
20474
|
+
agentNames.map(async (name) => {
|
|
20475
|
+
try {
|
|
20476
|
+
const profile = await this.profileLoader.loadProfile(name);
|
|
20477
|
+
return { name, profile, score: scoreAgent(task, profile) };
|
|
20478
|
+
} catch (error) {
|
|
20479
|
+
logger.debug(`[AgentSelector] Failed to load profile: ${name}`, { error });
|
|
20480
|
+
return null;
|
|
20481
|
+
}
|
|
20482
|
+
})
|
|
20483
|
+
);
|
|
20484
|
+
const scoredAgents = profileResults.filter(
|
|
20485
|
+
(result) => result !== null
|
|
20486
|
+
);
|
|
20487
|
+
if (scoredAgents.length === 0) {
|
|
20488
|
+
logger.warn("[AgentSelector] Failed to load any profiles, using fallback");
|
|
20489
|
+
return this.createFallbackResult(task);
|
|
20490
|
+
}
|
|
20491
|
+
scoredAgents.sort((a, b) => b.score - a.score);
|
|
20492
|
+
const best = scoredAgents[0];
|
|
20493
|
+
const alternatives = scoredAgents.slice(1, 4).map((a) => ({
|
|
20494
|
+
agent: a.name,
|
|
20495
|
+
score: a.score
|
|
20496
|
+
}));
|
|
20497
|
+
if (best.score < MIN_SELECTION_SCORE) {
|
|
20498
|
+
logger.info("[AgentSelector] Best score below threshold, using fallback", {
|
|
20499
|
+
bestAgent: best.name,
|
|
20500
|
+
bestScore: best.score,
|
|
20501
|
+
threshold: MIN_SELECTION_SCORE
|
|
20502
|
+
});
|
|
20503
|
+
const standardAgent = scoredAgents.find((a) => a.name === FALLBACK_AGENT);
|
|
20504
|
+
if (standardAgent) {
|
|
20505
|
+
return {
|
|
20506
|
+
agent: standardAgent.name,
|
|
20507
|
+
displayName: standardAgent.profile.displayName || standardAgent.name,
|
|
20508
|
+
role: standardAgent.profile.role,
|
|
20509
|
+
score: standardAgent.score,
|
|
20510
|
+
confidence: "low",
|
|
20511
|
+
rationale: ["No strong match found, using general-purpose agent"],
|
|
20512
|
+
alternatives: scoredAgents.filter((a) => a.name !== FALLBACK_AGENT).slice(0, 3).map((a) => ({ agent: a.name, score: a.score })),
|
|
20513
|
+
usedFallback: true
|
|
20514
|
+
};
|
|
20515
|
+
}
|
|
20516
|
+
return {
|
|
20517
|
+
agent: best.name,
|
|
20518
|
+
displayName: best.profile.displayName || best.name,
|
|
20519
|
+
role: best.profile.role,
|
|
20520
|
+
score: best.score,
|
|
20521
|
+
confidence: "low",
|
|
20522
|
+
rationale: ["Low confidence match - consider specifying agent explicitly"],
|
|
20523
|
+
alternatives,
|
|
20524
|
+
usedFallback: false
|
|
20525
|
+
};
|
|
20526
|
+
}
|
|
20527
|
+
const rationale = buildRationale(task, best.profile);
|
|
20528
|
+
const confidence = getConfidence(best.score);
|
|
20529
|
+
logger.info("[AgentSelector] Agent selected", {
|
|
20530
|
+
agent: best.name,
|
|
20531
|
+
score: best.score,
|
|
20532
|
+
confidence,
|
|
20533
|
+
rationale
|
|
20534
|
+
});
|
|
20535
|
+
return {
|
|
20536
|
+
agent: best.name,
|
|
20537
|
+
displayName: best.profile.displayName || best.name,
|
|
20538
|
+
role: best.profile.role,
|
|
20539
|
+
score: best.score,
|
|
20540
|
+
confidence,
|
|
20541
|
+
rationale,
|
|
20542
|
+
alternatives,
|
|
20543
|
+
usedFallback: false
|
|
20544
|
+
};
|
|
20545
|
+
}
|
|
20546
|
+
/**
|
|
20547
|
+
* Create a fallback result when no agents are available
|
|
20548
|
+
*/
|
|
20549
|
+
async createFallbackResult(_task) {
|
|
20550
|
+
try {
|
|
20551
|
+
const profile = await this.profileLoader.loadProfile(FALLBACK_AGENT);
|
|
20552
|
+
return {
|
|
20553
|
+
agent: FALLBACK_AGENT,
|
|
20554
|
+
displayName: profile.displayName || FALLBACK_AGENT,
|
|
20555
|
+
role: profile.role,
|
|
20556
|
+
score: 0,
|
|
20557
|
+
confidence: "low",
|
|
20558
|
+
rationale: ["No agents available, using fallback"],
|
|
20559
|
+
alternatives: [],
|
|
20560
|
+
usedFallback: true
|
|
20561
|
+
};
|
|
20562
|
+
} catch {
|
|
20563
|
+
return {
|
|
20564
|
+
agent: FALLBACK_AGENT,
|
|
20565
|
+
displayName: "Standard",
|
|
20566
|
+
role: "General-purpose agent",
|
|
20567
|
+
score: 0,
|
|
20568
|
+
confidence: "low",
|
|
20569
|
+
rationale: ["No agents available"],
|
|
20570
|
+
alternatives: [],
|
|
20571
|
+
usedFallback: true
|
|
20572
|
+
};
|
|
20573
|
+
}
|
|
20574
|
+
}
|
|
20575
|
+
};
|
|
20576
|
+
|
|
20351
20577
|
// src/mcp/tools/run-agent.ts
|
|
20352
20578
|
init_logger();
|
|
20353
20579
|
|
|
@@ -20647,22 +20873,41 @@ async function buildAgentContext(agentName, task, deps, callerProvider, bestProv
|
|
|
20647
20873
|
}
|
|
20648
20874
|
function createRunAgentHandler(deps) {
|
|
20649
20875
|
return async (input, context) => {
|
|
20650
|
-
const {
|
|
20876
|
+
const { task, provider, no_memory, mode = "auto" } = input;
|
|
20877
|
+
let { agent } = input;
|
|
20651
20878
|
if (context?.signal?.aborted) {
|
|
20652
20879
|
throw new Error("Request was cancelled");
|
|
20653
20880
|
}
|
|
20654
|
-
validateAgentName(agent);
|
|
20655
20881
|
validateStringParameter(task, "task", {
|
|
20656
20882
|
required: true,
|
|
20657
20883
|
minLength: 1,
|
|
20658
20884
|
maxLength: 1e4
|
|
20659
20885
|
});
|
|
20886
|
+
let autoSelected = false;
|
|
20887
|
+
if (!agent && deps.profileLoader) {
|
|
20888
|
+
const selector = new AgentSelector(deps.profileLoader);
|
|
20889
|
+
const selection = await selector.selectAgent(task);
|
|
20890
|
+
agent = selection.agent;
|
|
20891
|
+
autoSelected = true;
|
|
20892
|
+
logger.info("[MCP] run_agent auto-selected agent", {
|
|
20893
|
+
task: task.substring(0, 100),
|
|
20894
|
+
selectedAgent: agent,
|
|
20895
|
+
confidence: selection.confidence,
|
|
20896
|
+
score: selection.score,
|
|
20897
|
+
rationale: selection.rationale
|
|
20898
|
+
});
|
|
20899
|
+
}
|
|
20900
|
+
if (!agent) {
|
|
20901
|
+
throw new Error("Agent name is required when profileLoader is not available");
|
|
20902
|
+
}
|
|
20903
|
+
validateAgentName(agent);
|
|
20660
20904
|
const actualProvider = mapMcpProviderToActual(provider);
|
|
20661
20905
|
const session = deps.getSession?.() || null;
|
|
20662
20906
|
const callerProvider = session?.normalizedProvider || "unknown";
|
|
20663
20907
|
const callerActual = mapNormalizedCallerToActual(callerProvider);
|
|
20664
20908
|
logger.info("[MCP] run_agent called (Smart Routing v10.5.0)", {
|
|
20665
20909
|
agent,
|
|
20910
|
+
autoSelected,
|
|
20666
20911
|
task: task.substring(0, 100),
|
|
20667
20912
|
mcpProvider: provider,
|
|
20668
20913
|
actualProvider,
|
|
@@ -21475,20 +21720,35 @@ init_logger();
|
|
|
21475
21720
|
function createGetAgentContextHandler(deps) {
|
|
21476
21721
|
return async (input) => {
|
|
21477
21722
|
const {
|
|
21478
|
-
agent,
|
|
21479
21723
|
task,
|
|
21480
21724
|
includeMemory = true,
|
|
21481
21725
|
maxMemoryResults = 5
|
|
21482
21726
|
} = input;
|
|
21727
|
+
let { agent } = input;
|
|
21483
21728
|
const startTime = Date.now();
|
|
21484
|
-
validateAgentName(agent);
|
|
21485
21729
|
validateStringParameter(task, "task", {
|
|
21486
21730
|
required: true,
|
|
21487
21731
|
minLength: 1,
|
|
21488
21732
|
maxLength: 1e4
|
|
21489
21733
|
});
|
|
21734
|
+
let autoSelected = false;
|
|
21735
|
+
if (!agent) {
|
|
21736
|
+
const selector = new AgentSelector(deps.profileLoader);
|
|
21737
|
+
const selection = await selector.selectAgent(task);
|
|
21738
|
+
agent = selection.agent;
|
|
21739
|
+
autoSelected = true;
|
|
21740
|
+
logger.info("[MCP] get_agent_context auto-selected agent", {
|
|
21741
|
+
task: task.substring(0, 100),
|
|
21742
|
+
selectedAgent: agent,
|
|
21743
|
+
confidence: selection.confidence,
|
|
21744
|
+
score: selection.score,
|
|
21745
|
+
rationale: selection.rationale
|
|
21746
|
+
});
|
|
21747
|
+
}
|
|
21748
|
+
validateAgentName(agent);
|
|
21490
21749
|
logger.info("[MCP] get_agent_context called", {
|
|
21491
21750
|
agent,
|
|
21751
|
+
autoSelected,
|
|
21492
21752
|
task: task.substring(0, 100),
|
|
21493
21753
|
includeMemory,
|
|
21494
21754
|
maxMemoryResults
|
|
@@ -26039,17 +26299,24 @@ var McpServer = class _McpServer {
|
|
|
26039
26299
|
return [
|
|
26040
26300
|
{
|
|
26041
26301
|
name: "run_agent",
|
|
26042
|
-
description:
|
|
26302
|
+
description: `Execute an AutomatosX agent with a specific task.
|
|
26303
|
+
|
|
26304
|
+
v12.5.1: Agent auto-selection - if agent is omitted, system automatically selects the best agent based on task keywords.
|
|
26305
|
+
Uses Smart Routing: returns context for same-provider calls, spawns cross-provider execution.
|
|
26306
|
+
|
|
26307
|
+
Examples:
|
|
26308
|
+
- With agent: run_agent({ agent: "backend", task: "implement API" })
|
|
26309
|
+
- Auto-select: run_agent({ task: "fix bugs in the codebase" }) \u2192 selects "quality" agent`,
|
|
26043
26310
|
inputSchema: {
|
|
26044
26311
|
type: "object",
|
|
26045
26312
|
properties: {
|
|
26046
|
-
agent: { type: "string", description: "
|
|
26313
|
+
agent: { type: "string", description: "Optional: Agent name (e.g., backend, quality). If omitted, best agent is auto-selected based on task." },
|
|
26047
26314
|
task: { type: "string", description: "The task for the agent to perform" },
|
|
26048
26315
|
provider: { type: "string", description: "Optional: Override the AI provider", enum: ["claude", "gemini", "openai"] },
|
|
26049
26316
|
no_memory: { type: "boolean", description: "Optional: Skip memory injection", default: false },
|
|
26050
26317
|
mode: { type: "string", description: "Optional: Execution mode - auto (default), context (always return context), execute (always spawn)", enum: ["auto", "context", "execute"], default: "auto" }
|
|
26051
26318
|
},
|
|
26052
|
-
required: ["
|
|
26319
|
+
required: ["task"]
|
|
26053
26320
|
}
|
|
26054
26321
|
},
|
|
26055
26322
|
{
|
|
@@ -26161,16 +26428,18 @@ Use this tool first to understand what AutomatosX offers.`,
|
|
|
26161
26428
|
// v10.5.0: Smart Routing - Explicit context retrieval
|
|
26162
26429
|
{
|
|
26163
26430
|
name: "get_agent_context",
|
|
26164
|
-
description:
|
|
26431
|
+
description: `Get agent context without executing. Returns profile, relevant memory, and enhanced prompt for AI assistant to execute directly.
|
|
26432
|
+
|
|
26433
|
+
v12.5.1: Agent auto-selection - if agent is omitted, system automatically selects the best agent based on task keywords.`,
|
|
26165
26434
|
inputSchema: {
|
|
26166
26435
|
type: "object",
|
|
26167
26436
|
properties: {
|
|
26168
|
-
agent: { type: "string", description: "
|
|
26437
|
+
agent: { type: "string", description: "Optional: Agent name (e.g., backend, quality). If omitted, best agent is auto-selected based on task." },
|
|
26169
26438
|
task: { type: "string", description: "The task description for context building" },
|
|
26170
26439
|
includeMemory: { type: "boolean", description: "Include relevant memory entries (default: true)", default: true },
|
|
26171
26440
|
maxMemoryResults: { type: "number", description: "Maximum memory entries to return (default: 5)", default: 5 }
|
|
26172
26441
|
},
|
|
26173
|
-
required: ["
|
|
26442
|
+
required: ["task"]
|
|
26174
26443
|
}
|
|
26175
26444
|
},
|
|
26176
26445
|
// v11.3.5: Task Engine tools
|
|
@@ -26179,6 +26448,8 @@ Use this tool first to understand what AutomatosX offers.`,
|
|
|
26179
26448
|
getTaskResultSchema,
|
|
26180
26449
|
listTasksSchema,
|
|
26181
26450
|
deleteTaskSchema
|
|
26451
|
+
// v12.4.0: Bugfix tools intentionally NOT exposed via MCP
|
|
26452
|
+
// Access via: run_agent({ agent: "quality", task: "scan for bugs" })
|
|
26182
26453
|
];
|
|
26183
26454
|
}
|
|
26184
26455
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defai.digital/automatosx",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.5.1",
|
|
4
4
|
"description": "Provider-agnostic AI orchestration platform with 20+ specialized agents, persistent memory, and multi-provider routing for Claude Code, Gemini CLI, Codex CLI, GLM, and Grok",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|