156 lines
4.5 KiB
TypeScript
156 lines
4.5 KiB
TypeScript
// src/tools/chat/subagent.ts
|
|
// Copyright (C) 2025 DTP Technologies, LLC
|
|
// All Rights Reserved
|
|
|
|
import type { ToolDefinition } from "../../lib/ai-client.js";
|
|
|
|
import {
|
|
DtpTool,
|
|
type ToolArguments,
|
|
type ToolContext,
|
|
} from "../../lib/tool.js";
|
|
import AgentService from "../../services/agent.js";
|
|
import { ChatSessionMode } from "@/models/chat-session.js";
|
|
import HostMonitorService from "../../services/host-monitor.js";
|
|
|
|
const VALID_AGENT_TYPES = ["explore", "general"] as const;
|
|
type AgentType = (typeof VALID_AGENT_TYPES)[number];
|
|
|
|
export class SubagentTool extends DtpTool {
|
|
get name(): string {
|
|
return "SubagentTool";
|
|
}
|
|
get slug(): string {
|
|
return "subagent";
|
|
}
|
|
get metadata() {
|
|
return {
|
|
name: this.definition.function.name || "subagent",
|
|
category: "chat",
|
|
tags: ["subagent", "spawn", "delegate", "explore", "general"],
|
|
modes: [
|
|
ChatSessionMode.Plan,
|
|
ChatSessionMode.Build,
|
|
ChatSessionMode.Test,
|
|
ChatSessionMode.Ship,
|
|
ChatSessionMode.Develop,
|
|
],
|
|
};
|
|
}
|
|
|
|
public definition: ToolDefinition = {
|
|
type: "function",
|
|
function: {
|
|
name: "subagent",
|
|
description:
|
|
"Spawn a subagent to perform a specific task. The subagent will execute the task and return its result. Use 'explore' agent type for research and information gathering tasks. Use 'general' agent type for general-purpose task execution.",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
agent_type: {
|
|
type: "string",
|
|
enum: VALID_AGENT_TYPES,
|
|
description:
|
|
"The type of subagent to spawn. Use 'explore' for research and information gathering. Use 'general' for general-purpose task execution.",
|
|
},
|
|
prompt: {
|
|
type: "string",
|
|
description:
|
|
"The task description and instructions for the subagent. Be specific about what information to find or what task to perform.",
|
|
},
|
|
},
|
|
required: ["agent_type", "prompt"],
|
|
},
|
|
},
|
|
};
|
|
|
|
public async execute(
|
|
context: ToolContext,
|
|
args: ToolArguments,
|
|
): Promise<string> {
|
|
const { agent_type, prompt } = args;
|
|
|
|
if (!agent_type) {
|
|
return JSON.stringify({
|
|
success: false,
|
|
error: "MISSING_AGENT_TYPE",
|
|
message: "The 'agent_type' parameter is required.",
|
|
hint: "Specify either 'explore' or 'general' for the agent_type parameter.",
|
|
});
|
|
}
|
|
|
|
if (!VALID_AGENT_TYPES.includes(agent_type as AgentType)) {
|
|
return JSON.stringify({
|
|
success: false,
|
|
error: "INVALID_AGENT_TYPE",
|
|
message: `Invalid agent_type: '${agent_type}'. Must be one of: ${VALID_AGENT_TYPES.join(", ")}`,
|
|
hint: "Use 'explore' for research tasks or 'general' for general tasks.",
|
|
});
|
|
}
|
|
|
|
if (!prompt) {
|
|
return JSON.stringify({
|
|
success: false,
|
|
error: "MISSING_PROMPT",
|
|
message: "The 'prompt' parameter is required.",
|
|
hint: "Provide specific instructions for the subagent to execute.",
|
|
});
|
|
}
|
|
|
|
if (typeof prompt !== "string") {
|
|
return JSON.stringify({
|
|
success: false,
|
|
error: "INVALID_PROMPT_TYPE",
|
|
message: `The 'prompt' parameter must be a string, but received ${typeof prompt}.`,
|
|
hint: "Ensure you pass a string value for the prompt parameter.",
|
|
});
|
|
}
|
|
|
|
this.log.debug("Spawning subagent", {
|
|
agentType: agent_type,
|
|
promptLength: prompt.length,
|
|
});
|
|
|
|
try {
|
|
const result = await AgentService.spawnSubagent(
|
|
context.session,
|
|
agent_type as AgentType,
|
|
prompt,
|
|
);
|
|
|
|
const resultJson = JSON.stringify({
|
|
success: true,
|
|
data: {
|
|
agentType: agent_type,
|
|
result: result.response,
|
|
historyCount: result.history.length,
|
|
historyIds: result.historyIds,
|
|
subagentType: agent_type,
|
|
subagentPrompt: String(prompt),
|
|
subagentStats: result.stats,
|
|
},
|
|
});
|
|
const byteCount = Buffer.byteLength(resultJson, "utf-8");
|
|
HostMonitorService.subagent(byteCount);
|
|
HostMonitorService.toolCall(byteCount);
|
|
return resultJson;
|
|
} catch (error) {
|
|
const errorMessage =
|
|
error instanceof Error ? error.message : String(error);
|
|
|
|
this.log.error("Subagent execution failed", {
|
|
agentType: agent_type,
|
|
error: errorMessage,
|
|
});
|
|
|
|
return JSON.stringify({
|
|
success: false,
|
|
error: "SUBAGENT_FAILED",
|
|
message: errorMessage,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
export default new SubagentTool();
|