@defai.digital/automatosx 12.5.0 → 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 +1 -1
- package/dist/index.js +280 -237
- package/dist/mcp/index.js +280 -11
- 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.1 | 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.1"
|
|
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
|
|
@@ -31697,17 +31957,24 @@ var McpServer = class _McpServer {
|
|
|
31697
31957
|
return [
|
|
31698
31958
|
{
|
|
31699
31959
|
name: "run_agent",
|
|
31700
|
-
description:
|
|
31960
|
+
description: `Execute an AutomatosX agent with a specific task.
|
|
31961
|
+
|
|
31962
|
+
v12.5.1: Agent auto-selection - if agent is omitted, system automatically selects the best agent based on task keywords.
|
|
31963
|
+
Uses Smart Routing: returns context for same-provider calls, spawns cross-provider execution.
|
|
31964
|
+
|
|
31965
|
+
Examples:
|
|
31966
|
+
- With agent: run_agent({ agent: "backend", task: "implement API" })
|
|
31967
|
+
- Auto-select: run_agent({ task: "fix bugs in the codebase" }) \u2192 selects "quality" agent`,
|
|
31701
31968
|
inputSchema: {
|
|
31702
31969
|
type: "object",
|
|
31703
31970
|
properties: {
|
|
31704
|
-
agent: { type: "string", description: "
|
|
31971
|
+
agent: { type: "string", description: "Optional: Agent name (e.g., backend, quality). If omitted, best agent is auto-selected based on task." },
|
|
31705
31972
|
task: { type: "string", description: "The task for the agent to perform" },
|
|
31706
31973
|
provider: { type: "string", description: "Optional: Override the AI provider", enum: ["claude", "gemini", "openai"] },
|
|
31707
31974
|
no_memory: { type: "boolean", description: "Optional: Skip memory injection", default: false },
|
|
31708
31975
|
mode: { type: "string", description: "Optional: Execution mode - auto (default), context (always return context), execute (always spawn)", enum: ["auto", "context", "execute"], default: "auto" }
|
|
31709
31976
|
},
|
|
31710
|
-
required: ["
|
|
31977
|
+
required: ["task"]
|
|
31711
31978
|
}
|
|
31712
31979
|
},
|
|
31713
31980
|
{
|
|
@@ -31819,16 +32086,18 @@ Use this tool first to understand what AutomatosX offers.`,
|
|
|
31819
32086
|
// v10.5.0: Smart Routing - Explicit context retrieval
|
|
31820
32087
|
{
|
|
31821
32088
|
name: "get_agent_context",
|
|
31822
|
-
description:
|
|
32089
|
+
description: `Get agent context without executing. Returns profile, relevant memory, and enhanced prompt for AI assistant to execute directly.
|
|
32090
|
+
|
|
32091
|
+
v12.5.1: Agent auto-selection - if agent is omitted, system automatically selects the best agent based on task keywords.`,
|
|
31823
32092
|
inputSchema: {
|
|
31824
32093
|
type: "object",
|
|
31825
32094
|
properties: {
|
|
31826
|
-
agent: { type: "string", description: "
|
|
32095
|
+
agent: { type: "string", description: "Optional: Agent name (e.g., backend, quality). If omitted, best agent is auto-selected based on task." },
|
|
31827
32096
|
task: { type: "string", description: "The task description for context building" },
|
|
31828
32097
|
includeMemory: { type: "boolean", description: "Include relevant memory entries (default: true)", default: true },
|
|
31829
32098
|
maxMemoryResults: { type: "number", description: "Maximum memory entries to return (default: 5)", default: 5 }
|
|
31830
32099
|
},
|
|
31831
|
-
required: ["
|
|
32100
|
+
required: ["task"]
|
|
31832
32101
|
}
|
|
31833
32102
|
},
|
|
31834
32103
|
// v11.3.5: Task Engine tools
|
|
@@ -35189,232 +35458,6 @@ var memoryCommand = {
|
|
|
35189
35458
|
// src/cli/commands/run.ts
|
|
35190
35459
|
init_esm_shims();
|
|
35191
35460
|
|
|
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
35461
|
// src/core/stage-execution-controller.ts
|
|
35419
35462
|
init_esm_shims();
|
|
35420
35463
|
|
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.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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defai.digital/automatosx",
|
|
3
|
-
"version": "12.5.
|
|
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": {
|