Skip to content

Commit 9fd000b

Browse files
committed
feat: add Task tool and subagent support to AI chat
Enable the Task tool so the AI can spawn researcher and coder subagents for focused subtasks. Render subagent invocations in the chat UI with a dedicated icon, label, and expandable description.
1 parent 98e3db2 commit 9fd000b

3 files changed

Lines changed: 50 additions & 2 deletions

File tree

src-node/claude-code-agent.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,37 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale)
250250
maxTurns: undefined,
251251
allowedTools: [
252252
"Read", "Edit", "Write", "Glob", "Grep",
253-
"AskUserQuestion",
253+
"AskUserQuestion", "Task",
254254
"mcp__phoenix-editor__getEditorState",
255255
"mcp__phoenix-editor__takeScreenshot",
256256
"mcp__phoenix-editor__execJsInLivePreview",
257257
"mcp__phoenix-editor__controlEditor",
258258
"mcp__phoenix-editor__resizeLivePreview",
259259
"mcp__phoenix-editor__wait"
260260
],
261+
agents: {
262+
"researcher": {
263+
description: "Explores the codebase, reads files, and searches" +
264+
" for patterns. Use for research tasks.",
265+
prompt: "You are a code research assistant. Search and read" +
266+
" files to answer questions. Do not modify files.",
267+
tools: ["Read", "Glob", "Grep",
268+
"mcp__phoenix-editor__getEditorState",
269+
"mcp__phoenix-editor__takeScreenshot",
270+
"mcp__phoenix-editor__execJsInLivePreview"]
271+
},
272+
"coder": {
273+
description: "Reads, edits, and writes code files." +
274+
" Use for implementation tasks.",
275+
prompt: "You are a coding assistant. Implement the requested" +
276+
" changes using Edit for existing files and Write" +
277+
" only for new files.",
278+
tools: ["Read", "Edit", "Write", "Glob", "Grep",
279+
"mcp__phoenix-editor__getEditorState",
280+
"mcp__phoenix-editor__takeScreenshot",
281+
"mcp__phoenix-editor__execJsInLivePreview"]
282+
}
283+
},
261284
mcpServers: { "phoenix-editor": editorMcpServer },
262285
permissionMode: "acceptEdits",
263286
appendSystemPrompt:

src/core-ai/AIChatPanel.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,8 @@ define(function (require, exports, module) {
643643
"mcp__phoenix-editor__resizeLivePreview": { icon: "fa-solid fa-arrows-left-right", color: "#66bb6a", label: Strings.AI_CHAT_TOOL_RESIZE_PREVIEW },
644644
"mcp__phoenix-editor__wait": { icon: "fa-solid fa-hourglass-half", color: "#adb9bd", label: Strings.AI_CHAT_TOOL_WAIT },
645645
TodoWrite: { icon: "fa-solid fa-list-check", color: "#66bb6a", label: Strings.AI_CHAT_TOOL_TASKS },
646-
AskUserQuestion: { icon: "fa-solid fa-circle-question", color: "#66bb6a", label: Strings.AI_CHAT_TOOL_QUESTION }
646+
AskUserQuestion: { icon: "fa-solid fa-circle-question", color: "#66bb6a", label: Strings.AI_CHAT_TOOL_QUESTION },
647+
Task: { icon: "fa-solid fa-diagram-project", color: "#6b9eff", label: Strings.AI_CHAT_TOOL_TASK }
647648
};
648649

649650
function _onProgress(_event, data) {
@@ -1542,6 +1543,17 @@ define(function (require, exports, module) {
15421543
$tool.find(".ai-tool-header").on("click", function () {
15431544
$tool.toggleClass("ai-tool-expanded");
15441545
}).css("cursor", "pointer");
1546+
} else if (toolName === "Task" && toolInput) {
1547+
const $detail = $('<div class="ai-tool-detail"></div>');
1548+
const desc = toolInput.description || toolInput.prompt || "";
1549+
if (desc) {
1550+
$detail.append($('<div class="ai-tool-detail-line"></div>').text(desc.slice(0, 200)));
1551+
}
1552+
$tool.append($detail);
1553+
$tool.addClass("ai-tool-expanded");
1554+
$tool.find(".ai-tool-header").on("click", function () {
1555+
$tool.toggleClass("ai-tool-expanded");
1556+
}).css("cursor", "pointer");
15451557
} else if (detail.lines && detail.lines.length) {
15461558
// Add expandable detail if available
15471559
const $detail = $('<div class="ai-tool-detail"></div>');
@@ -1674,6 +1686,17 @@ define(function (require, exports, module) {
16741686
lines: qs.map(function (q) { return q.question; })
16751687
};
16761688
}
1689+
case "Task": {
1690+
const desc = input.description || input.prompt || "";
1691+
const agentType = input.subagent_type || "";
1692+
const summary = agentType
1693+
? StringUtils.format(Strings.AI_CHAT_TOOL_TASK_NAME, agentType)
1694+
: Strings.AI_CHAT_TOOL_TASK;
1695+
return {
1696+
summary: summary,
1697+
lines: desc ? [desc.split("\n")[0].slice(0, 120)] : []
1698+
};
1699+
}
16771700
case "TodoWrite": {
16781701
const todos = input.todos || [];
16791702
const completed = todos.filter(function (t) { return t.status === "completed"; }).length;

src/nls/root/strings.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,6 +1879,8 @@ define({
18791879
"AI_CHAT_COPY_CODE": "Copy",
18801880
"AI_CHAT_COPIED_CODE": "Copied!",
18811881
"AI_CHAT_TOOL_QUESTION": "Question",
1882+
"AI_CHAT_TOOL_TASK": "Subagent",
1883+
"AI_CHAT_TOOL_TASK_NAME": "Subagent: {0}",
18821884
"AI_CHAT_QUESTION_OTHER": "Type a custom answer\u2026",
18831885

18841886
// demo start - Phoenix Code Playground - Interactive Onboarding

0 commit comments

Comments
 (0)