@defai.digital/automatosx 12.5.0 → 12.5.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/README.md +1 -1
- package/dist/index.js +305 -258
- package/dist/mcp/index.js +305 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
[](https://ubuntu.com)
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
|
|
15
|
-
**Status**: ✅ **Production Ready** | v12.5.
|
|
15
|
+
**Status**: ✅ **Production Ready** | v12.5.2 | MCP Hybrid Framing & Multi-Protocol Support
|
|
16
16
|
|
|
17
17
|
> 🎯 **What AutomatosX Does**: Adds 20+ specialized agents, persistent memory, workflow automation, and 80% cost savings to Claude Code/Codex - **without changing how you work**.
|
|
18
18
|
|
package/dist/index.js
CHANGED
|
@@ -9431,7 +9431,7 @@ var PRECOMPILED_CONFIG = {
|
|
|
9431
9431
|
"enableFreeTierPrioritization": true,
|
|
9432
9432
|
"enableWorkloadAwareRouting": true
|
|
9433
9433
|
},
|
|
9434
|
-
"version": "12.5.
|
|
9434
|
+
"version": "12.5.2"
|
|
9435
9435
|
};
|
|
9436
9436
|
|
|
9437
9437
|
// src/core/config/schemas.ts
|
|
@@ -26006,6 +26006,232 @@ ${context.task}`;
|
|
|
26006
26006
|
}
|
|
26007
26007
|
};
|
|
26008
26008
|
|
|
26009
|
+
// src/agents/agent-selector.ts
|
|
26010
|
+
init_esm_shims();
|
|
26011
|
+
init_logger();
|
|
26012
|
+
function scoreAgent(task, profile) {
|
|
26013
|
+
let score = 0;
|
|
26014
|
+
const taskLower = task.toLowerCase();
|
|
26015
|
+
if (profile.selectionMetadata?.primaryIntents) {
|
|
26016
|
+
for (const intent of profile.selectionMetadata.primaryIntents) {
|
|
26017
|
+
const intentKeywords = intent.toLowerCase().split(/\s+/);
|
|
26018
|
+
const matchedKeywords = intentKeywords.filter(
|
|
26019
|
+
(keyword) => taskLower.includes(keyword) && keyword.length > 3
|
|
26020
|
+
);
|
|
26021
|
+
if (matchedKeywords.length >= 2) {
|
|
26022
|
+
score += 10;
|
|
26023
|
+
} else if (matchedKeywords.length === 1) {
|
|
26024
|
+
score += 5;
|
|
26025
|
+
}
|
|
26026
|
+
}
|
|
26027
|
+
}
|
|
26028
|
+
if (profile.selectionMetadata?.secondarySignals) {
|
|
26029
|
+
for (const signal of profile.selectionMetadata.secondarySignals) {
|
|
26030
|
+
if (taskLower.includes(signal.toLowerCase())) {
|
|
26031
|
+
score += 5;
|
|
26032
|
+
}
|
|
26033
|
+
}
|
|
26034
|
+
}
|
|
26035
|
+
if (profile.selectionMetadata?.negativeIntents) {
|
|
26036
|
+
for (const negative of profile.selectionMetadata.negativeIntents) {
|
|
26037
|
+
const keywords = negative.split("(")[0]?.toLowerCase() || "";
|
|
26038
|
+
const negativeKeywords = keywords.split(/\s+/).filter((k) => k.length > 3);
|
|
26039
|
+
const matchedNegative = negativeKeywords.filter(
|
|
26040
|
+
(keyword) => taskLower.includes(keyword)
|
|
26041
|
+
);
|
|
26042
|
+
if (matchedNegative.length >= 2) {
|
|
26043
|
+
score -= 20;
|
|
26044
|
+
}
|
|
26045
|
+
}
|
|
26046
|
+
}
|
|
26047
|
+
if (profile.selectionMetadata?.redirectWhen) {
|
|
26048
|
+
for (const rule of profile.selectionMetadata.redirectWhen) {
|
|
26049
|
+
try {
|
|
26050
|
+
const regex = new RegExp(rule.phrase, "i");
|
|
26051
|
+
if (regex.test(task)) {
|
|
26052
|
+
score -= 15;
|
|
26053
|
+
}
|
|
26054
|
+
} catch (error) {
|
|
26055
|
+
logger.debug("Invalid regex pattern in redirectWhen rule", {
|
|
26056
|
+
pattern: rule.phrase,
|
|
26057
|
+
error: error instanceof Error ? error.message : String(error)
|
|
26058
|
+
});
|
|
26059
|
+
}
|
|
26060
|
+
}
|
|
26061
|
+
}
|
|
26062
|
+
if (profile.abilitySelection?.taskBased) {
|
|
26063
|
+
for (const keyword of Object.keys(profile.abilitySelection.taskBased)) {
|
|
26064
|
+
if (taskLower.includes(keyword.toLowerCase())) {
|
|
26065
|
+
score += 3;
|
|
26066
|
+
}
|
|
26067
|
+
}
|
|
26068
|
+
}
|
|
26069
|
+
return Math.max(0, score);
|
|
26070
|
+
}
|
|
26071
|
+
function buildRationale(task, profile) {
|
|
26072
|
+
const rationale = [];
|
|
26073
|
+
const taskLower = task.toLowerCase();
|
|
26074
|
+
if (profile.selectionMetadata?.primaryIntents) {
|
|
26075
|
+
const matchedIntents = profile.selectionMetadata.primaryIntents.filter((intent) => {
|
|
26076
|
+
const keywords = intent.toLowerCase().split(/\s+/);
|
|
26077
|
+
return keywords.some((k) => taskLower.includes(k) && k.length > 3);
|
|
26078
|
+
});
|
|
26079
|
+
if (matchedIntents.length > 0) {
|
|
26080
|
+
rationale.push(`Matches: ${matchedIntents.slice(0, 2).join(", ")}`);
|
|
26081
|
+
}
|
|
26082
|
+
}
|
|
26083
|
+
if (profile.selectionMetadata?.secondarySignals) {
|
|
26084
|
+
const matchedSignals = profile.selectionMetadata.secondarySignals.filter(
|
|
26085
|
+
(signal) => taskLower.includes(signal.toLowerCase())
|
|
26086
|
+
);
|
|
26087
|
+
if (matchedSignals.length > 0) {
|
|
26088
|
+
rationale.push(`Keywords: ${matchedSignals.slice(0, 3).join(", ")}`);
|
|
26089
|
+
}
|
|
26090
|
+
}
|
|
26091
|
+
if (profile.abilitySelection?.taskBased) {
|
|
26092
|
+
const matchedAbilities = Object.keys(profile.abilitySelection.taskBased).filter(
|
|
26093
|
+
(keyword) => taskLower.includes(keyword.toLowerCase())
|
|
26094
|
+
);
|
|
26095
|
+
if (matchedAbilities.length > 0) {
|
|
26096
|
+
rationale.push(`Abilities: ${matchedAbilities.slice(0, 2).join(", ")}`);
|
|
26097
|
+
}
|
|
26098
|
+
}
|
|
26099
|
+
if (rationale.length === 0) {
|
|
26100
|
+
rationale.push("General capability match");
|
|
26101
|
+
}
|
|
26102
|
+
return rationale;
|
|
26103
|
+
}
|
|
26104
|
+
function getConfidence(score) {
|
|
26105
|
+
if (score >= 30) return "high";
|
|
26106
|
+
if (score >= 15) return "medium";
|
|
26107
|
+
return "low";
|
|
26108
|
+
}
|
|
26109
|
+
var MIN_SELECTION_SCORE = 5;
|
|
26110
|
+
var FALLBACK_AGENT = "standard";
|
|
26111
|
+
var AgentSelector = class {
|
|
26112
|
+
profileLoader;
|
|
26113
|
+
constructor(profileLoader) {
|
|
26114
|
+
this.profileLoader = profileLoader;
|
|
26115
|
+
}
|
|
26116
|
+
/**
|
|
26117
|
+
* Select the best agent for a task
|
|
26118
|
+
*
|
|
26119
|
+
* @param task - Task description
|
|
26120
|
+
* @returns Selection result with agent, score, confidence, and rationale
|
|
26121
|
+
*/
|
|
26122
|
+
async selectAgent(task) {
|
|
26123
|
+
logger.debug("[AgentSelector] Selecting agent for task", {
|
|
26124
|
+
taskPreview: task.substring(0, 100)
|
|
26125
|
+
});
|
|
26126
|
+
const agentNames = await this.profileLoader.listProfiles();
|
|
26127
|
+
if (agentNames.length === 0) {
|
|
26128
|
+
logger.warn("[AgentSelector] No agents found, using fallback");
|
|
26129
|
+
return this.createFallbackResult(task);
|
|
26130
|
+
}
|
|
26131
|
+
const profileResults = await Promise.all(
|
|
26132
|
+
agentNames.map(async (name) => {
|
|
26133
|
+
try {
|
|
26134
|
+
const profile = await this.profileLoader.loadProfile(name);
|
|
26135
|
+
return { name, profile, score: scoreAgent(task, profile) };
|
|
26136
|
+
} catch (error) {
|
|
26137
|
+
logger.debug(`[AgentSelector] Failed to load profile: ${name}`, { error });
|
|
26138
|
+
return null;
|
|
26139
|
+
}
|
|
26140
|
+
})
|
|
26141
|
+
);
|
|
26142
|
+
const scoredAgents = profileResults.filter(
|
|
26143
|
+
(result) => result !== null
|
|
26144
|
+
);
|
|
26145
|
+
if (scoredAgents.length === 0) {
|
|
26146
|
+
logger.warn("[AgentSelector] Failed to load any profiles, using fallback");
|
|
26147
|
+
return this.createFallbackResult(task);
|
|
26148
|
+
}
|
|
26149
|
+
scoredAgents.sort((a, b) => b.score - a.score);
|
|
26150
|
+
const best = scoredAgents[0];
|
|
26151
|
+
const alternatives = scoredAgents.slice(1, 4).map((a) => ({
|
|
26152
|
+
agent: a.name,
|
|
26153
|
+
score: a.score
|
|
26154
|
+
}));
|
|
26155
|
+
if (best.score < MIN_SELECTION_SCORE) {
|
|
26156
|
+
logger.info("[AgentSelector] Best score below threshold, using fallback", {
|
|
26157
|
+
bestAgent: best.name,
|
|
26158
|
+
bestScore: best.score,
|
|
26159
|
+
threshold: MIN_SELECTION_SCORE
|
|
26160
|
+
});
|
|
26161
|
+
const standardAgent = scoredAgents.find((a) => a.name === FALLBACK_AGENT);
|
|
26162
|
+
if (standardAgent) {
|
|
26163
|
+
return {
|
|
26164
|
+
agent: standardAgent.name,
|
|
26165
|
+
displayName: standardAgent.profile.displayName || standardAgent.name,
|
|
26166
|
+
role: standardAgent.profile.role,
|
|
26167
|
+
score: standardAgent.score,
|
|
26168
|
+
confidence: "low",
|
|
26169
|
+
rationale: ["No strong match found, using general-purpose agent"],
|
|
26170
|
+
alternatives: scoredAgents.filter((a) => a.name !== FALLBACK_AGENT).slice(0, 3).map((a) => ({ agent: a.name, score: a.score })),
|
|
26171
|
+
usedFallback: true
|
|
26172
|
+
};
|
|
26173
|
+
}
|
|
26174
|
+
return {
|
|
26175
|
+
agent: best.name,
|
|
26176
|
+
displayName: best.profile.displayName || best.name,
|
|
26177
|
+
role: best.profile.role,
|
|
26178
|
+
score: best.score,
|
|
26179
|
+
confidence: "low",
|
|
26180
|
+
rationale: ["Low confidence match - consider specifying agent explicitly"],
|
|
26181
|
+
alternatives,
|
|
26182
|
+
usedFallback: false
|
|
26183
|
+
};
|
|
26184
|
+
}
|
|
26185
|
+
const rationale = buildRationale(task, best.profile);
|
|
26186
|
+
const confidence = getConfidence(best.score);
|
|
26187
|
+
logger.info("[AgentSelector] Agent selected", {
|
|
26188
|
+
agent: best.name,
|
|
26189
|
+
score: best.score,
|
|
26190
|
+
confidence,
|
|
26191
|
+
rationale
|
|
26192
|
+
});
|
|
26193
|
+
return {
|
|
26194
|
+
agent: best.name,
|
|
26195
|
+
displayName: best.profile.displayName || best.name,
|
|
26196
|
+
role: best.profile.role,
|
|
26197
|
+
score: best.score,
|
|
26198
|
+
confidence,
|
|
26199
|
+
rationale,
|
|
26200
|
+
alternatives,
|
|
26201
|
+
usedFallback: false
|
|
26202
|
+
};
|
|
26203
|
+
}
|
|
26204
|
+
/**
|
|
26205
|
+
* Create a fallback result when no agents are available
|
|
26206
|
+
*/
|
|
26207
|
+
async createFallbackResult(_task) {
|
|
26208
|
+
try {
|
|
26209
|
+
const profile = await this.profileLoader.loadProfile(FALLBACK_AGENT);
|
|
26210
|
+
return {
|
|
26211
|
+
agent: FALLBACK_AGENT,
|
|
26212
|
+
displayName: profile.displayName || FALLBACK_AGENT,
|
|
26213
|
+
role: profile.role,
|
|
26214
|
+
score: 0,
|
|
26215
|
+
confidence: "low",
|
|
26216
|
+
rationale: ["No agents available, using fallback"],
|
|
26217
|
+
alternatives: [],
|
|
26218
|
+
usedFallback: true
|
|
26219
|
+
};
|
|
26220
|
+
} catch {
|
|
26221
|
+
return {
|
|
26222
|
+
agent: FALLBACK_AGENT,
|
|
26223
|
+
displayName: "Standard",
|
|
26224
|
+
role: "General-purpose agent",
|
|
26225
|
+
score: 0,
|
|
26226
|
+
confidence: "low",
|
|
26227
|
+
rationale: ["No agents available"],
|
|
26228
|
+
alternatives: [],
|
|
26229
|
+
usedFallback: true
|
|
26230
|
+
};
|
|
26231
|
+
}
|
|
26232
|
+
}
|
|
26233
|
+
};
|
|
26234
|
+
|
|
26009
26235
|
// src/mcp/tools/run-agent.ts
|
|
26010
26236
|
init_logger();
|
|
26011
26237
|
|
|
@@ -26305,22 +26531,41 @@ async function buildAgentContext(agentName, task, deps, callerProvider, bestProv
|
|
|
26305
26531
|
}
|
|
26306
26532
|
function createRunAgentHandler(deps) {
|
|
26307
26533
|
return async (input, context) => {
|
|
26308
|
-
const {
|
|
26534
|
+
const { task, provider, no_memory, mode = "auto" } = input;
|
|
26535
|
+
let { agent } = input;
|
|
26309
26536
|
if (context?.signal?.aborted) {
|
|
26310
26537
|
throw new Error("Request was cancelled");
|
|
26311
26538
|
}
|
|
26312
|
-
validateAgentName(agent);
|
|
26313
26539
|
validateStringParameter(task, "task", {
|
|
26314
26540
|
required: true,
|
|
26315
26541
|
minLength: 1,
|
|
26316
26542
|
maxLength: 1e4
|
|
26317
26543
|
});
|
|
26544
|
+
let autoSelected = false;
|
|
26545
|
+
if (!agent && deps.profileLoader) {
|
|
26546
|
+
const selector = new AgentSelector(deps.profileLoader);
|
|
26547
|
+
const selection = await selector.selectAgent(task);
|
|
26548
|
+
agent = selection.agent;
|
|
26549
|
+
autoSelected = true;
|
|
26550
|
+
logger.info("[MCP] run_agent auto-selected agent", {
|
|
26551
|
+
task: task.substring(0, 100),
|
|
26552
|
+
selectedAgent: agent,
|
|
26553
|
+
confidence: selection.confidence,
|
|
26554
|
+
score: selection.score,
|
|
26555
|
+
rationale: selection.rationale
|
|
26556
|
+
});
|
|
26557
|
+
}
|
|
26558
|
+
if (!agent) {
|
|
26559
|
+
throw new Error("Agent name is required when profileLoader is not available");
|
|
26560
|
+
}
|
|
26561
|
+
validateAgentName(agent);
|
|
26318
26562
|
const actualProvider = mapMcpProviderToActual(provider);
|
|
26319
26563
|
const session = deps.getSession?.() || null;
|
|
26320
26564
|
const callerProvider = session?.normalizedProvider || "unknown";
|
|
26321
26565
|
const callerActual = mapNormalizedCallerToActual(callerProvider);
|
|
26322
26566
|
logger.info("[MCP] run_agent called (Smart Routing v10.5.0)", {
|
|
26323
26567
|
agent,
|
|
26568
|
+
autoSelected,
|
|
26324
26569
|
task: task.substring(0, 100),
|
|
26325
26570
|
mcpProvider: provider,
|
|
26326
26571
|
actualProvider,
|
|
@@ -27133,20 +27378,35 @@ init_logger();
|
|
|
27133
27378
|
function createGetAgentContextHandler(deps) {
|
|
27134
27379
|
return async (input) => {
|
|
27135
27380
|
const {
|
|
27136
|
-
agent,
|
|
27137
27381
|
task,
|
|
27138
27382
|
includeMemory = true,
|
|
27139
27383
|
maxMemoryResults = 5
|
|
27140
27384
|
} = input;
|
|
27385
|
+
let { agent } = input;
|
|
27141
27386
|
const startTime = Date.now();
|
|
27142
|
-
validateAgentName(agent);
|
|
27143
27387
|
validateStringParameter(task, "task", {
|
|
27144
27388
|
required: true,
|
|
27145
27389
|
minLength: 1,
|
|
27146
27390
|
maxLength: 1e4
|
|
27147
27391
|
});
|
|
27392
|
+
let autoSelected = false;
|
|
27393
|
+
if (!agent) {
|
|
27394
|
+
const selector = new AgentSelector(deps.profileLoader);
|
|
27395
|
+
const selection = await selector.selectAgent(task);
|
|
27396
|
+
agent = selection.agent;
|
|
27397
|
+
autoSelected = true;
|
|
27398
|
+
logger.info("[MCP] get_agent_context auto-selected agent", {
|
|
27399
|
+
task: task.substring(0, 100),
|
|
27400
|
+
selectedAgent: agent,
|
|
27401
|
+
confidence: selection.confidence,
|
|
27402
|
+
score: selection.score,
|
|
27403
|
+
rationale: selection.rationale
|
|
27404
|
+
});
|
|
27405
|
+
}
|
|
27406
|
+
validateAgentName(agent);
|
|
27148
27407
|
logger.info("[MCP] get_agent_context called", {
|
|
27149
27408
|
agent,
|
|
27409
|
+
autoSelected,
|
|
27150
27410
|
task: task.substring(0, 100),
|
|
27151
27411
|
includeMemory,
|
|
27152
27412
|
maxMemoryResults
|
|
@@ -31561,7 +31821,12 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
|
|
|
31561
31821
|
profile.role ? `**Role:** ${profile.role}` : "",
|
|
31562
31822
|
profile.abilities?.length ? `**Abilities:** ${profile.abilities.join(", ")}` : "",
|
|
31563
31823
|
"",
|
|
31564
|
-
profile.systemPrompt || "No system prompt defined."
|
|
31824
|
+
profile.systemPrompt || "No system prompt defined.",
|
|
31825
|
+
"",
|
|
31826
|
+
"## Profile JSON",
|
|
31827
|
+
"```json",
|
|
31828
|
+
JSON.stringify(profile, null, 2),
|
|
31829
|
+
"```"
|
|
31565
31830
|
].filter(Boolean).join("\n");
|
|
31566
31831
|
return {
|
|
31567
31832
|
uri: `agent/${agent}`,
|
|
@@ -31569,8 +31834,7 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
|
|
|
31569
31834
|
description: `AutomatosX agent profile for ${agent}`,
|
|
31570
31835
|
mimeType: "text/markdown",
|
|
31571
31836
|
contents: [
|
|
31572
|
-
{ type: "text", text: summary }
|
|
31573
|
-
{ type: "application/json", json: profile }
|
|
31837
|
+
{ type: "text", text: summary }
|
|
31574
31838
|
]
|
|
31575
31839
|
};
|
|
31576
31840
|
}
|
|
@@ -31588,8 +31852,7 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
|
|
|
31588
31852
|
description: `Workspace ${isPrd ? "PRD" : "tmp"} file`,
|
|
31589
31853
|
mimeType: "text/markdown",
|
|
31590
31854
|
contents: [
|
|
31591
|
-
{ type: "text", text: content }
|
|
31592
|
-
{ type: "application/json", json: { path: path7, content, workspace: isPrd ? "PRD" : "tmp" } }
|
|
31855
|
+
{ type: "text", text: content }
|
|
31593
31856
|
]
|
|
31594
31857
|
};
|
|
31595
31858
|
}
|
|
@@ -31697,17 +31960,24 @@ var McpServer = class _McpServer {
|
|
|
31697
31960
|
return [
|
|
31698
31961
|
{
|
|
31699
31962
|
name: "run_agent",
|
|
31700
|
-
description:
|
|
31963
|
+
description: `Execute an AutomatosX agent with a specific task.
|
|
31964
|
+
|
|
31965
|
+
v12.5.1: Agent auto-selection - if agent is omitted, system automatically selects the best agent based on task keywords.
|
|
31966
|
+
Uses Smart Routing: returns context for same-provider calls, spawns cross-provider execution.
|
|
31967
|
+
|
|
31968
|
+
Examples:
|
|
31969
|
+
- With agent: run_agent({ agent: "backend", task: "implement API" })
|
|
31970
|
+
- Auto-select: run_agent({ task: "fix bugs in the codebase" }) \u2192 selects "quality" agent`,
|
|
31701
31971
|
inputSchema: {
|
|
31702
31972
|
type: "object",
|
|
31703
31973
|
properties: {
|
|
31704
|
-
agent: { type: "string", description: "
|
|
31974
|
+
agent: { type: "string", description: "Optional: Agent name (e.g., backend, quality). If omitted, best agent is auto-selected based on task." },
|
|
31705
31975
|
task: { type: "string", description: "The task for the agent to perform" },
|
|
31706
31976
|
provider: { type: "string", description: "Optional: Override the AI provider", enum: ["claude", "gemini", "openai"] },
|
|
31707
31977
|
no_memory: { type: "boolean", description: "Optional: Skip memory injection", default: false },
|
|
31708
31978
|
mode: { type: "string", description: "Optional: Execution mode - auto (default), context (always return context), execute (always spawn)", enum: ["auto", "context", "execute"], default: "auto" }
|
|
31709
31979
|
},
|
|
31710
|
-
required: ["
|
|
31980
|
+
required: ["task"]
|
|
31711
31981
|
}
|
|
31712
31982
|
},
|
|
31713
31983
|
{
|
|
@@ -31819,16 +32089,18 @@ Use this tool first to understand what AutomatosX offers.`,
|
|
|
31819
32089
|
// v10.5.0: Smart Routing - Explicit context retrieval
|
|
31820
32090
|
{
|
|
31821
32091
|
name: "get_agent_context",
|
|
31822
|
-
description:
|
|
32092
|
+
description: `Get agent context without executing. Returns profile, relevant memory, and enhanced prompt for AI assistant to execute directly.
|
|
32093
|
+
|
|
32094
|
+
v12.5.1: Agent auto-selection - if agent is omitted, system automatically selects the best agent based on task keywords.`,
|
|
31823
32095
|
inputSchema: {
|
|
31824
32096
|
type: "object",
|
|
31825
32097
|
properties: {
|
|
31826
|
-
agent: { type: "string", description: "
|
|
32098
|
+
agent: { type: "string", description: "Optional: Agent name (e.g., backend, quality). If omitted, best agent is auto-selected based on task." },
|
|
31827
32099
|
task: { type: "string", description: "The task description for context building" },
|
|
31828
32100
|
includeMemory: { type: "boolean", description: "Include relevant memory entries (default: true)", default: true },
|
|
31829
32101
|
maxMemoryResults: { type: "number", description: "Maximum memory entries to return (default: 5)", default: 5 }
|
|
31830
32102
|
},
|
|
31831
|
-
required: ["
|
|
32103
|
+
required: ["task"]
|
|
31832
32104
|
}
|
|
31833
32105
|
},
|
|
31834
32106
|
// v11.3.5: Task Engine tools
|
|
@@ -32226,8 +32498,10 @@ Use this tool first to understand what AutomatosX offers.`,
|
|
|
32226
32498
|
const profile = await this.profileLoader.loadProfile(agent);
|
|
32227
32499
|
const content = [
|
|
32228
32500
|
{ type: "text", text: `System prompt for ${agent}:
|
|
32229
|
-
${profile.systemPrompt || "No system prompt defined."}
|
|
32230
|
-
|
|
32501
|
+
${profile.systemPrompt || "No system prompt defined."}
|
|
32502
|
+
|
|
32503
|
+
Profile:
|
|
32504
|
+
${JSON.stringify(profile, null, 2)}` }
|
|
32231
32505
|
];
|
|
32232
32506
|
return { jsonrpc: "2.0", id, result: { prompt: { name, description: "Agent context", arguments: [{ name: "agent", required: true }] }, content } };
|
|
32233
32507
|
} catch (error) {
|
|
@@ -32244,8 +32518,10 @@ ${profile.systemPrompt || "No system prompt defined."}` },
|
|
|
32244
32518
|
{ type: "text", text: `AutomatosX MCP status:
|
|
32245
32519
|
Version: ${summary.version}
|
|
32246
32520
|
Providers: ${summary.providerCount}
|
|
32247
|
-
Streaming: ${summary.streamingNotifications}
|
|
32248
|
-
|
|
32521
|
+
Streaming: ${summary.streamingNotifications}
|
|
32522
|
+
|
|
32523
|
+
Details:
|
|
32524
|
+
${JSON.stringify(summary, null, 2)}` }
|
|
32249
32525
|
];
|
|
32250
32526
|
return { jsonrpc: "2.0", id, result: { prompt: { name, description: "AutomatosX status" }, content } };
|
|
32251
32527
|
}
|
|
@@ -32270,11 +32546,15 @@ Streaming: ${summary.streamingNotifications}` },
|
|
|
32270
32546
|
profile.role ? `**Role:** ${profile.role}` : "",
|
|
32271
32547
|
profile.abilities?.length ? `**Abilities:** ${profile.abilities.join(", ")}` : "",
|
|
32272
32548
|
"",
|
|
32273
|
-
profile.systemPrompt || "No system prompt defined."
|
|
32549
|
+
profile.systemPrompt || "No system prompt defined.",
|
|
32550
|
+
"",
|
|
32551
|
+
"## Profile JSON",
|
|
32552
|
+
"```json",
|
|
32553
|
+
JSON.stringify(profile, null, 2),
|
|
32554
|
+
"```"
|
|
32274
32555
|
].filter(Boolean).join("\n");
|
|
32275
32556
|
const contents = [
|
|
32276
|
-
{ type: "text", text: summary }
|
|
32277
|
-
{ type: "application/json", json: profile }
|
|
32557
|
+
{ type: "text", text: summary }
|
|
32278
32558
|
];
|
|
32279
32559
|
return { jsonrpc: "2.0", id, result: { uri, mimeType: "text/markdown", contents } };
|
|
32280
32560
|
} catch (error) {
|
|
@@ -32317,15 +32597,8 @@ Streaming: ${summary.streamingNotifications}` },
|
|
|
32317
32597
|
}
|
|
32318
32598
|
/** Create MCP tool response wrapper */
|
|
32319
32599
|
createToolResponse(id, result, isError = false) {
|
|
32320
|
-
|
|
32321
|
-
|
|
32322
|
-
content = [{ type: "text", text: result }];
|
|
32323
|
-
} else {
|
|
32324
|
-
content = [
|
|
32325
|
-
{ type: "application/json", json: result },
|
|
32326
|
-
{ type: "text", text: JSON.stringify(result, null, 2) }
|
|
32327
|
-
];
|
|
32328
|
-
}
|
|
32600
|
+
const text = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
32601
|
+
const content = [{ type: "text", text }];
|
|
32329
32602
|
const response = { content, ...isError && { isError } };
|
|
32330
32603
|
return { jsonrpc: "2.0", id, result: response };
|
|
32331
32604
|
}
|
|
@@ -35189,232 +35462,6 @@ var memoryCommand = {
|
|
|
35189
35462
|
// src/cli/commands/run.ts
|
|
35190
35463
|
init_esm_shims();
|
|
35191
35464
|
|
|
35192
|
-
// src/agents/agent-selector.ts
|
|
35193
|
-
init_esm_shims();
|
|
35194
|
-
init_logger();
|
|
35195
|
-
function scoreAgent(task, profile) {
|
|
35196
|
-
let score = 0;
|
|
35197
|
-
const taskLower = task.toLowerCase();
|
|
35198
|
-
if (profile.selectionMetadata?.primaryIntents) {
|
|
35199
|
-
for (const intent of profile.selectionMetadata.primaryIntents) {
|
|
35200
|
-
const intentKeywords = intent.toLowerCase().split(/\s+/);
|
|
35201
|
-
const matchedKeywords = intentKeywords.filter(
|
|
35202
|
-
(keyword) => taskLower.includes(keyword) && keyword.length > 3
|
|
35203
|
-
);
|
|
35204
|
-
if (matchedKeywords.length >= 2) {
|
|
35205
|
-
score += 10;
|
|
35206
|
-
} else if (matchedKeywords.length === 1) {
|
|
35207
|
-
score += 5;
|
|
35208
|
-
}
|
|
35209
|
-
}
|
|
35210
|
-
}
|
|
35211
|
-
if (profile.selectionMetadata?.secondarySignals) {
|
|
35212
|
-
for (const signal of profile.selectionMetadata.secondarySignals) {
|
|
35213
|
-
if (taskLower.includes(signal.toLowerCase())) {
|
|
35214
|
-
score += 5;
|
|
35215
|
-
}
|
|
35216
|
-
}
|
|
35217
|
-
}
|
|
35218
|
-
if (profile.selectionMetadata?.negativeIntents) {
|
|
35219
|
-
for (const negative of profile.selectionMetadata.negativeIntents) {
|
|
35220
|
-
const keywords = negative.split("(")[0]?.toLowerCase() || "";
|
|
35221
|
-
const negativeKeywords = keywords.split(/\s+/).filter((k) => k.length > 3);
|
|
35222
|
-
const matchedNegative = negativeKeywords.filter(
|
|
35223
|
-
(keyword) => taskLower.includes(keyword)
|
|
35224
|
-
);
|
|
35225
|
-
if (matchedNegative.length >= 2) {
|
|
35226
|
-
score -= 20;
|
|
35227
|
-
}
|
|
35228
|
-
}
|
|
35229
|
-
}
|
|
35230
|
-
if (profile.selectionMetadata?.redirectWhen) {
|
|
35231
|
-
for (const rule of profile.selectionMetadata.redirectWhen) {
|
|
35232
|
-
try {
|
|
35233
|
-
const regex = new RegExp(rule.phrase, "i");
|
|
35234
|
-
if (regex.test(task)) {
|
|
35235
|
-
score -= 15;
|
|
35236
|
-
}
|
|
35237
|
-
} catch (error) {
|
|
35238
|
-
logger.debug("Invalid regex pattern in redirectWhen rule", {
|
|
35239
|
-
pattern: rule.phrase,
|
|
35240
|
-
error: error instanceof Error ? error.message : String(error)
|
|
35241
|
-
});
|
|
35242
|
-
}
|
|
35243
|
-
}
|
|
35244
|
-
}
|
|
35245
|
-
if (profile.abilitySelection?.taskBased) {
|
|
35246
|
-
for (const keyword of Object.keys(profile.abilitySelection.taskBased)) {
|
|
35247
|
-
if (taskLower.includes(keyword.toLowerCase())) {
|
|
35248
|
-
score += 3;
|
|
35249
|
-
}
|
|
35250
|
-
}
|
|
35251
|
-
}
|
|
35252
|
-
return Math.max(0, score);
|
|
35253
|
-
}
|
|
35254
|
-
function buildRationale(task, profile) {
|
|
35255
|
-
const rationale = [];
|
|
35256
|
-
const taskLower = task.toLowerCase();
|
|
35257
|
-
if (profile.selectionMetadata?.primaryIntents) {
|
|
35258
|
-
const matchedIntents = profile.selectionMetadata.primaryIntents.filter((intent) => {
|
|
35259
|
-
const keywords = intent.toLowerCase().split(/\s+/);
|
|
35260
|
-
return keywords.some((k) => taskLower.includes(k) && k.length > 3);
|
|
35261
|
-
});
|
|
35262
|
-
if (matchedIntents.length > 0) {
|
|
35263
|
-
rationale.push(`Matches: ${matchedIntents.slice(0, 2).join(", ")}`);
|
|
35264
|
-
}
|
|
35265
|
-
}
|
|
35266
|
-
if (profile.selectionMetadata?.secondarySignals) {
|
|
35267
|
-
const matchedSignals = profile.selectionMetadata.secondarySignals.filter(
|
|
35268
|
-
(signal) => taskLower.includes(signal.toLowerCase())
|
|
35269
|
-
);
|
|
35270
|
-
if (matchedSignals.length > 0) {
|
|
35271
|
-
rationale.push(`Keywords: ${matchedSignals.slice(0, 3).join(", ")}`);
|
|
35272
|
-
}
|
|
35273
|
-
}
|
|
35274
|
-
if (profile.abilitySelection?.taskBased) {
|
|
35275
|
-
const matchedAbilities = Object.keys(profile.abilitySelection.taskBased).filter(
|
|
35276
|
-
(keyword) => taskLower.includes(keyword.toLowerCase())
|
|
35277
|
-
);
|
|
35278
|
-
if (matchedAbilities.length > 0) {
|
|
35279
|
-
rationale.push(`Abilities: ${matchedAbilities.slice(0, 2).join(", ")}`);
|
|
35280
|
-
}
|
|
35281
|
-
}
|
|
35282
|
-
if (rationale.length === 0) {
|
|
35283
|
-
rationale.push("General capability match");
|
|
35284
|
-
}
|
|
35285
|
-
return rationale;
|
|
35286
|
-
}
|
|
35287
|
-
function getConfidence(score) {
|
|
35288
|
-
if (score >= 30) return "high";
|
|
35289
|
-
if (score >= 15) return "medium";
|
|
35290
|
-
return "low";
|
|
35291
|
-
}
|
|
35292
|
-
var MIN_SELECTION_SCORE = 5;
|
|
35293
|
-
var FALLBACK_AGENT = "standard";
|
|
35294
|
-
var AgentSelector = class {
|
|
35295
|
-
profileLoader;
|
|
35296
|
-
constructor(profileLoader) {
|
|
35297
|
-
this.profileLoader = profileLoader;
|
|
35298
|
-
}
|
|
35299
|
-
/**
|
|
35300
|
-
* Select the best agent for a task
|
|
35301
|
-
*
|
|
35302
|
-
* @param task - Task description
|
|
35303
|
-
* @returns Selection result with agent, score, confidence, and rationale
|
|
35304
|
-
*/
|
|
35305
|
-
async selectAgent(task) {
|
|
35306
|
-
logger.debug("[AgentSelector] Selecting agent for task", {
|
|
35307
|
-
taskPreview: task.substring(0, 100)
|
|
35308
|
-
});
|
|
35309
|
-
const agentNames = await this.profileLoader.listProfiles();
|
|
35310
|
-
if (agentNames.length === 0) {
|
|
35311
|
-
logger.warn("[AgentSelector] No agents found, using fallback");
|
|
35312
|
-
return this.createFallbackResult(task);
|
|
35313
|
-
}
|
|
35314
|
-
const profileResults = await Promise.all(
|
|
35315
|
-
agentNames.map(async (name) => {
|
|
35316
|
-
try {
|
|
35317
|
-
const profile = await this.profileLoader.loadProfile(name);
|
|
35318
|
-
return { name, profile, score: scoreAgent(task, profile) };
|
|
35319
|
-
} catch (error) {
|
|
35320
|
-
logger.debug(`[AgentSelector] Failed to load profile: ${name}`, { error });
|
|
35321
|
-
return null;
|
|
35322
|
-
}
|
|
35323
|
-
})
|
|
35324
|
-
);
|
|
35325
|
-
const scoredAgents = profileResults.filter(
|
|
35326
|
-
(result) => result !== null
|
|
35327
|
-
);
|
|
35328
|
-
if (scoredAgents.length === 0) {
|
|
35329
|
-
logger.warn("[AgentSelector] Failed to load any profiles, using fallback");
|
|
35330
|
-
return this.createFallbackResult(task);
|
|
35331
|
-
}
|
|
35332
|
-
scoredAgents.sort((a, b) => b.score - a.score);
|
|
35333
|
-
const best = scoredAgents[0];
|
|
35334
|
-
const alternatives = scoredAgents.slice(1, 4).map((a) => ({
|
|
35335
|
-
agent: a.name,
|
|
35336
|
-
score: a.score
|
|
35337
|
-
}));
|
|
35338
|
-
if (best.score < MIN_SELECTION_SCORE) {
|
|
35339
|
-
logger.info("[AgentSelector] Best score below threshold, using fallback", {
|
|
35340
|
-
bestAgent: best.name,
|
|
35341
|
-
bestScore: best.score,
|
|
35342
|
-
threshold: MIN_SELECTION_SCORE
|
|
35343
|
-
});
|
|
35344
|
-
const standardAgent = scoredAgents.find((a) => a.name === FALLBACK_AGENT);
|
|
35345
|
-
if (standardAgent) {
|
|
35346
|
-
return {
|
|
35347
|
-
agent: standardAgent.name,
|
|
35348
|
-
displayName: standardAgent.profile.displayName || standardAgent.name,
|
|
35349
|
-
role: standardAgent.profile.role,
|
|
35350
|
-
score: standardAgent.score,
|
|
35351
|
-
confidence: "low",
|
|
35352
|
-
rationale: ["No strong match found, using general-purpose agent"],
|
|
35353
|
-
alternatives: scoredAgents.filter((a) => a.name !== FALLBACK_AGENT).slice(0, 3).map((a) => ({ agent: a.name, score: a.score })),
|
|
35354
|
-
usedFallback: true
|
|
35355
|
-
};
|
|
35356
|
-
}
|
|
35357
|
-
return {
|
|
35358
|
-
agent: best.name,
|
|
35359
|
-
displayName: best.profile.displayName || best.name,
|
|
35360
|
-
role: best.profile.role,
|
|
35361
|
-
score: best.score,
|
|
35362
|
-
confidence: "low",
|
|
35363
|
-
rationale: ["Low confidence match - consider specifying agent explicitly"],
|
|
35364
|
-
alternatives,
|
|
35365
|
-
usedFallback: false
|
|
35366
|
-
};
|
|
35367
|
-
}
|
|
35368
|
-
const rationale = buildRationale(task, best.profile);
|
|
35369
|
-
const confidence = getConfidence(best.score);
|
|
35370
|
-
logger.info("[AgentSelector] Agent selected", {
|
|
35371
|
-
agent: best.name,
|
|
35372
|
-
score: best.score,
|
|
35373
|
-
confidence,
|
|
35374
|
-
rationale
|
|
35375
|
-
});
|
|
35376
|
-
return {
|
|
35377
|
-
agent: best.name,
|
|
35378
|
-
displayName: best.profile.displayName || best.name,
|
|
35379
|
-
role: best.profile.role,
|
|
35380
|
-
score: best.score,
|
|
35381
|
-
confidence,
|
|
35382
|
-
rationale,
|
|
35383
|
-
alternatives,
|
|
35384
|
-
usedFallback: false
|
|
35385
|
-
};
|
|
35386
|
-
}
|
|
35387
|
-
/**
|
|
35388
|
-
* Create a fallback result when no agents are available
|
|
35389
|
-
*/
|
|
35390
|
-
async createFallbackResult(_task) {
|
|
35391
|
-
try {
|
|
35392
|
-
const profile = await this.profileLoader.loadProfile(FALLBACK_AGENT);
|
|
35393
|
-
return {
|
|
35394
|
-
agent: FALLBACK_AGENT,
|
|
35395
|
-
displayName: profile.displayName || FALLBACK_AGENT,
|
|
35396
|
-
role: profile.role,
|
|
35397
|
-
score: 0,
|
|
35398
|
-
confidence: "low",
|
|
35399
|
-
rationale: ["No agents available, using fallback"],
|
|
35400
|
-
alternatives: [],
|
|
35401
|
-
usedFallback: true
|
|
35402
|
-
};
|
|
35403
|
-
} catch {
|
|
35404
|
-
return {
|
|
35405
|
-
agent: FALLBACK_AGENT,
|
|
35406
|
-
displayName: "Standard",
|
|
35407
|
-
role: "General-purpose agent",
|
|
35408
|
-
score: 0,
|
|
35409
|
-
confidence: "low",
|
|
35410
|
-
rationale: ["No agents available"],
|
|
35411
|
-
alternatives: [],
|
|
35412
|
-
usedFallback: true
|
|
35413
|
-
};
|
|
35414
|
-
}
|
|
35415
|
-
}
|
|
35416
|
-
};
|
|
35417
|
-
|
|
35418
35465
|
// src/core/stage-execution-controller.ts
|
|
35419
35466
|
init_esm_shims();
|
|
35420
35467
|
|
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.5.
|
|
8730
|
+
"version": "12.5.2"
|
|
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
|
|
@@ -25903,7 +26163,12 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
|
|
|
25903
26163
|
profile.role ? `**Role:** ${profile.role}` : "",
|
|
25904
26164
|
profile.abilities?.length ? `**Abilities:** ${profile.abilities.join(", ")}` : "",
|
|
25905
26165
|
"",
|
|
25906
|
-
profile.systemPrompt || "No system prompt defined."
|
|
26166
|
+
profile.systemPrompt || "No system prompt defined.",
|
|
26167
|
+
"",
|
|
26168
|
+
"## Profile JSON",
|
|
26169
|
+
"```json",
|
|
26170
|
+
JSON.stringify(profile, null, 2),
|
|
26171
|
+
"```"
|
|
25907
26172
|
].filter(Boolean).join("\n");
|
|
25908
26173
|
return {
|
|
25909
26174
|
uri: `agent/${agent}`,
|
|
@@ -25911,8 +26176,7 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
|
|
|
25911
26176
|
description: `AutomatosX agent profile for ${agent}`,
|
|
25912
26177
|
mimeType: "text/markdown",
|
|
25913
26178
|
contents: [
|
|
25914
|
-
{ type: "text", text: summary }
|
|
25915
|
-
{ type: "application/json", json: profile }
|
|
26179
|
+
{ type: "text", text: summary }
|
|
25916
26180
|
]
|
|
25917
26181
|
};
|
|
25918
26182
|
}
|
|
@@ -25930,8 +26194,7 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
|
|
|
25930
26194
|
description: `Workspace ${isPrd ? "PRD" : "tmp"} file`,
|
|
25931
26195
|
mimeType: "text/markdown",
|
|
25932
26196
|
contents: [
|
|
25933
|
-
{ type: "text", text: content }
|
|
25934
|
-
{ type: "application/json", json: { path: path7, content, workspace: isPrd ? "PRD" : "tmp" } }
|
|
26197
|
+
{ type: "text", text: content }
|
|
25935
26198
|
]
|
|
25936
26199
|
};
|
|
25937
26200
|
}
|
|
@@ -26039,17 +26302,24 @@ var McpServer = class _McpServer {
|
|
|
26039
26302
|
return [
|
|
26040
26303
|
{
|
|
26041
26304
|
name: "run_agent",
|
|
26042
|
-
description:
|
|
26305
|
+
description: `Execute an AutomatosX agent with a specific task.
|
|
26306
|
+
|
|
26307
|
+
v12.5.1: Agent auto-selection - if agent is omitted, system automatically selects the best agent based on task keywords.
|
|
26308
|
+
Uses Smart Routing: returns context for same-provider calls, spawns cross-provider execution.
|
|
26309
|
+
|
|
26310
|
+
Examples:
|
|
26311
|
+
- With agent: run_agent({ agent: "backend", task: "implement API" })
|
|
26312
|
+
- Auto-select: run_agent({ task: "fix bugs in the codebase" }) \u2192 selects "quality" agent`,
|
|
26043
26313
|
inputSchema: {
|
|
26044
26314
|
type: "object",
|
|
26045
26315
|
properties: {
|
|
26046
|
-
agent: { type: "string", description: "
|
|
26316
|
+
agent: { type: "string", description: "Optional: Agent name (e.g., backend, quality). If omitted, best agent is auto-selected based on task." },
|
|
26047
26317
|
task: { type: "string", description: "The task for the agent to perform" },
|
|
26048
26318
|
provider: { type: "string", description: "Optional: Override the AI provider", enum: ["claude", "gemini", "openai"] },
|
|
26049
26319
|
no_memory: { type: "boolean", description: "Optional: Skip memory injection", default: false },
|
|
26050
26320
|
mode: { type: "string", description: "Optional: Execution mode - auto (default), context (always return context), execute (always spawn)", enum: ["auto", "context", "execute"], default: "auto" }
|
|
26051
26321
|
},
|
|
26052
|
-
required: ["
|
|
26322
|
+
required: ["task"]
|
|
26053
26323
|
}
|
|
26054
26324
|
},
|
|
26055
26325
|
{
|
|
@@ -26161,16 +26431,18 @@ Use this tool first to understand what AutomatosX offers.`,
|
|
|
26161
26431
|
// v10.5.0: Smart Routing - Explicit context retrieval
|
|
26162
26432
|
{
|
|
26163
26433
|
name: "get_agent_context",
|
|
26164
|
-
description:
|
|
26434
|
+
description: `Get agent context without executing. Returns profile, relevant memory, and enhanced prompt for AI assistant to execute directly.
|
|
26435
|
+
|
|
26436
|
+
v12.5.1: Agent auto-selection - if agent is omitted, system automatically selects the best agent based on task keywords.`,
|
|
26165
26437
|
inputSchema: {
|
|
26166
26438
|
type: "object",
|
|
26167
26439
|
properties: {
|
|
26168
|
-
agent: { type: "string", description: "
|
|
26440
|
+
agent: { type: "string", description: "Optional: Agent name (e.g., backend, quality). If omitted, best agent is auto-selected based on task." },
|
|
26169
26441
|
task: { type: "string", description: "The task description for context building" },
|
|
26170
26442
|
includeMemory: { type: "boolean", description: "Include relevant memory entries (default: true)", default: true },
|
|
26171
26443
|
maxMemoryResults: { type: "number", description: "Maximum memory entries to return (default: 5)", default: 5 }
|
|
26172
26444
|
},
|
|
26173
|
-
required: ["
|
|
26445
|
+
required: ["task"]
|
|
26174
26446
|
}
|
|
26175
26447
|
},
|
|
26176
26448
|
// v11.3.5: Task Engine tools
|
|
@@ -26568,8 +26840,10 @@ Use this tool first to understand what AutomatosX offers.`,
|
|
|
26568
26840
|
const profile = await this.profileLoader.loadProfile(agent);
|
|
26569
26841
|
const content = [
|
|
26570
26842
|
{ type: "text", text: `System prompt for ${agent}:
|
|
26571
|
-
${profile.systemPrompt || "No system prompt defined."}
|
|
26572
|
-
|
|
26843
|
+
${profile.systemPrompt || "No system prompt defined."}
|
|
26844
|
+
|
|
26845
|
+
Profile:
|
|
26846
|
+
${JSON.stringify(profile, null, 2)}` }
|
|
26573
26847
|
];
|
|
26574
26848
|
return { jsonrpc: "2.0", id, result: { prompt: { name, description: "Agent context", arguments: [{ name: "agent", required: true }] }, content } };
|
|
26575
26849
|
} catch (error) {
|
|
@@ -26586,8 +26860,10 @@ ${profile.systemPrompt || "No system prompt defined."}` },
|
|
|
26586
26860
|
{ type: "text", text: `AutomatosX MCP status:
|
|
26587
26861
|
Version: ${summary.version}
|
|
26588
26862
|
Providers: ${summary.providerCount}
|
|
26589
|
-
Streaming: ${summary.streamingNotifications}
|
|
26590
|
-
|
|
26863
|
+
Streaming: ${summary.streamingNotifications}
|
|
26864
|
+
|
|
26865
|
+
Details:
|
|
26866
|
+
${JSON.stringify(summary, null, 2)}` }
|
|
26591
26867
|
];
|
|
26592
26868
|
return { jsonrpc: "2.0", id, result: { prompt: { name, description: "AutomatosX status" }, content } };
|
|
26593
26869
|
}
|
|
@@ -26612,11 +26888,15 @@ Streaming: ${summary.streamingNotifications}` },
|
|
|
26612
26888
|
profile.role ? `**Role:** ${profile.role}` : "",
|
|
26613
26889
|
profile.abilities?.length ? `**Abilities:** ${profile.abilities.join(", ")}` : "",
|
|
26614
26890
|
"",
|
|
26615
|
-
profile.systemPrompt || "No system prompt defined."
|
|
26891
|
+
profile.systemPrompt || "No system prompt defined.",
|
|
26892
|
+
"",
|
|
26893
|
+
"## Profile JSON",
|
|
26894
|
+
"```json",
|
|
26895
|
+
JSON.stringify(profile, null, 2),
|
|
26896
|
+
"```"
|
|
26616
26897
|
].filter(Boolean).join("\n");
|
|
26617
26898
|
const contents = [
|
|
26618
|
-
{ type: "text", text: summary }
|
|
26619
|
-
{ type: "application/json", json: profile }
|
|
26899
|
+
{ type: "text", text: summary }
|
|
26620
26900
|
];
|
|
26621
26901
|
return { jsonrpc: "2.0", id, result: { uri, mimeType: "text/markdown", contents } };
|
|
26622
26902
|
} catch (error) {
|
|
@@ -26659,15 +26939,8 @@ Streaming: ${summary.streamingNotifications}` },
|
|
|
26659
26939
|
}
|
|
26660
26940
|
/** Create MCP tool response wrapper */
|
|
26661
26941
|
createToolResponse(id, result, isError = false) {
|
|
26662
|
-
|
|
26663
|
-
|
|
26664
|
-
content = [{ type: "text", text: result }];
|
|
26665
|
-
} else {
|
|
26666
|
-
content = [
|
|
26667
|
-
{ type: "application/json", json: result },
|
|
26668
|
-
{ type: "text", text: JSON.stringify(result, null, 2) }
|
|
26669
|
-
];
|
|
26670
|
-
}
|
|
26942
|
+
const text = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
26943
|
+
const content = [{ type: "text", text }];
|
|
26671
26944
|
const response = { content, ...isError && { isError } };
|
|
26672
26945
|
return { jsonrpc: "2.0", id, result: response };
|
|
26673
26946
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defai.digital/automatosx",
|
|
3
|
-
"version": "12.5.
|
|
3
|
+
"version": "12.5.2",
|
|
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": {
|