Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
32af25f
feat: subagents
uinstinct Dec 11, 2025
a78be7c
support streaming into tool call output
uinstinct Dec 11, 2025
675378f
rename `subagent_type` to `subagent_name`
uinstinct Dec 11, 2025
1a06d69
refactor subagent namings
uinstinct Dec 11, 2025
c2af5a9
allow all tools inside subagents
uinstinct Dec 11, 2025
1c448c4
fix: resolve circular dependency in subagent tool
continue[bot] Dec 15, 2025
87fd9b6
fix: resolve circular dependency in subagent executor
continue[bot] Dec 15, 2025
6a5f80b
fix: break circular dependency by extracting tool names
continue[bot] Dec 15, 2025
26bef77
fix: correct built-in tool names list
continue[bot] Dec 15, 2025
2003128
fix: correct import order in ToolPermissionService
continue[bot] Dec 15, 2025
bcdf012
Merge branch 'main' into sub-agents
uinstinct Dec 18, 2025
85eb249
wip: use the first found apply model for subagent
uinstinct Dec 18, 2025
0cc7a16
get subagents from config
uinstinct Dec 19, 2025
53becf1
remove debug statements
uinstinct Dec 19, 2025
70d5be8
rename builtInAgents to get-agents
uinstinct Dec 19, 2025
08465a6
add `subagent` in model roles
uinstinct Dec 19, 2025
b427287
Merge branch 'main' into sub-agents
uinstinct Jan 6, 2026
5abe556
pass modelstate to read subagents
uinstinct Jan 7, 2026
27ac8cc
include model roles subagent
uinstinct Jan 7, 2026
8381812
allow escaping of subagent tool using event emit
uinstinct Jan 7, 2026
d510de9
remove builtintoolnames
uinstinct Jan 7, 2026
8e02122
cleanup listener after execution
uinstinct Jan 7, 2026
c366fa8
fix lint
uinstinct Jan 7, 2026
3bdac8d
move subagent behind beta
uinstinct Jan 7, 2026
a48bb94
fix more lints
uinstinct Jan 7, 2026
6182a3f
restore toolpermissionservice changes
uinstinct Jan 8, 2026
fc5e22f
fix cyclical import
uinstinct Jan 8, 2026
25b08e0
fix gitaiintegration test
uinstinct Jan 8, 2026
66fe98f
try to fix import issues for tests
uinstinct Jan 8, 2026
eb77a58
use subagent tool meta instead of calling the func
uinstinct Jan 8, 2026
3fbb428
add subagent tests
uinstinct Jan 8, 2026
2b347b6
use dynamic to prevent cyclical dependency
uinstinct Jan 8, 2026
c2d928d
fix subagent tests
uinstinct Jan 8, 2026
d55a138
decouple allbuiltins and subagent tool meta
uinstinct Jan 9, 2026
72da793
skip dynamic imports
uinstinct Jan 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/config/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@
}
if (name === "llm") {
const llm = models.find((model) => model.title === params?.modelTitle);
if (!llm) {

Check warning on line 467 in core/config/load.ts

View workflow job for this annotation

GitHub Actions / core-checks

Unexpected negated condition
errors.push({
fatal: false,
message: `Unknown reranking model ${params?.modelTitle}`,
Expand Down Expand Up @@ -514,6 +514,7 @@
autocomplete: [...tabAutocompleteModels],
embed: newEmbedder ? [newEmbedder] : [],
rerank: newReranker ? [newReranker] : [],
subagent: [],
},
selectedModelByRole: {
chat: null, // Not implemented (uses GUI defaultModel)
Expand All @@ -523,6 +524,7 @@
autocomplete: null,
rerank: newReranker ?? null,
summarize: null, // Not implemented
subagent: null,
},
rules: [],
};
Expand Down Expand Up @@ -558,7 +560,7 @@
id: `continue-mcp-server-${index + 1}`,
name: `MCP Server`,
requestOptions: mergeConfigYamlRequestOptions(
server.transport.type !== "stdio"

Check warning on line 563 in core/config/load.ts

View workflow job for this annotation

GitHub Actions / core-checks

Unexpected negated condition
? server.transport.requestOptions
: undefined,
config.requestOptions,
Expand Down
12 changes: 12 additions & 0 deletions core/config/usesFreeTrialApiKey.vitest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: [],
rerank: [],
embed: [],
subagent: [],
},
selectedModelByRole: {
chat: null,
Expand All @@ -67,6 +68,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: null,
rerank: null,
embed: null,
subagent: null,
},
contextProviders: [],
slashCommands: [],
Expand Down Expand Up @@ -106,6 +108,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: [],
rerank: [],
embed: [],
subagent: [],
},
selectedModelByRole: {
chat: null,
Expand All @@ -115,6 +118,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: null,
rerank: null,
embed: null,
subagent: null,
},
contextProviders: [],
slashCommands: [],
Expand Down Expand Up @@ -166,6 +170,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: [],
rerank: [],
embed: [],
subagent: [],
},
selectedModelByRole: {
chat: null,
Expand All @@ -175,6 +180,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: null,
rerank: null,
embed: null,
subagent: null,
},
contextProviders: [],
slashCommands: [],
Expand Down Expand Up @@ -227,6 +233,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: [],
rerank: [],
embed: [],
subagent: [],
},
selectedModelByRole: {
chat: null,
Expand All @@ -236,6 +243,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: null,
rerank: null,
embed: null,
subagent: null,
},
contextProviders: [],
slashCommands: [],
Expand Down Expand Up @@ -281,6 +289,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: [],
rerank: [],
embed: [],
subagent: [],
},
selectedModelByRole: {
chat: null,
Expand All @@ -290,6 +299,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: null,
rerank: null,
embed: null,
subagent: null,
},
contextProviders: [],
slashCommands: [],
Expand Down Expand Up @@ -323,6 +333,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: [],
rerank: [],
embed: [],
subagent: [],
},
selectedModelByRole: {
chat: null,
Expand All @@ -332,6 +343,7 @@ describe("usesFreeTrialApiKey", () => {
autocomplete: null,
rerank: null,
embed: null,
subagent: null,
},
contextProviders: [],
slashCommands: [],
Expand Down
6 changes: 6 additions & 0 deletions core/config/yaml/loadYaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ export async function configYamlToContinueConfig(options: {
autocomplete: [],
rerank: [],
summarize: [],
subagent: [],
},
selectedModelByRole: {
chat: null,
Expand All @@ -196,6 +197,7 @@ export async function configYamlToContinueConfig(options: {
autocomplete: null,
rerank: null,
summarize: null,
subagent: null,
},
rules: [],
requestOptions: { ...config.requestOptions },
Expand Down Expand Up @@ -333,6 +335,10 @@ export async function configYamlToContinueConfig(options: {
if (model.roles?.includes("rerank")) {
continueConfig.modelsByRole.rerank.push(...llms);
}

if (model.roles?.includes("subagent")) {
continueConfig.modelsByRole.subagent.push(...llms);
}
} catch (e) {
localErrors.push({
fatal: false,
Expand Down
2 changes: 2 additions & 0 deletions core/config/yaml/models.vitest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ describe("llmsFromModelConfig requestOptions merging", () => {
embed: null,
rerank: null,
summarize: null,
subagent: null,
},
modelsByRole: {
apply: [],
Expand All @@ -76,6 +77,7 @@ describe("llmsFromModelConfig requestOptions merging", () => {
embed: [],
rerank: [],
summarize: [],
subagent: [],
},
slashCommands: [],
tools: [],
Expand Down
2 changes: 2 additions & 0 deletions extensions/cli/src/commands/BaseCommandOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export interface BaseCommandOptions {
agent?: string;
/** Enable beta UploadArtifact tool */
betaUploadArtifactTool?: boolean;
/** Enable beta Subagent tool */
betaSubagentTool?: boolean;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions extensions/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ addCommonOptions(program)
)
.option("--resume", "Resume from last session")
.option("--fork <sessionId>", "Fork from an existing session ID")
.option(
"--beta-subagent-tool",
"Enable beta Subagent tool for invoking subagents",
)
.action(async (prompt, options) => {
// Telemetry: record command invocation
await posthogService.capture("cliCommand", { command: "cn" });
Expand Down
21 changes: 21 additions & 0 deletions extensions/cli/src/services/ModelService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,4 +305,25 @@ export class ModelService
return nameMatches;
});
}

static getSubagentModels(modelState: ModelServiceState) {
if (!modelState.assistant) {
return [];
}
const subagentModels = modelState.assistant.models
?.filter((model) => !!model)
.filter((model) => !!model.name) // filter out models without a name
.filter((model) => model.roles?.includes("subagent")) // filter with role subagent
.filter((model) => !!model.chatOptions?.baseSystemMessage); // filter those with a system message

if (!subagentModels) {
return [];
}
return subagentModels?.map((model) => ({
llmApi: createLlmApi(model, modelState.authConfig),
model,
assistant: modelState.assistant,
authConfig: modelState.authConfig,
}));
}
}
10 changes: 9 additions & 1 deletion extensions/cli/src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { loadAuthConfig } from "../auth/workos.js";
import { initializeWithOnboarding } from "../onboarding.js";
import { setBetaUploadArtifactToolEnabled } from "../tools/toolsConfig.js";
import {
setBetaSubagentToolEnabled,
setBetaUploadArtifactToolEnabled,
} from "../tools/toolsConfig.js";
import { logger } from "../util/logger.js";

import { AgentFileService } from "./AgentFileService.js";
Expand Down Expand Up @@ -62,6 +65,9 @@ export async function initializeServices(initOptions: ServiceInitOptions = {}) {
if (commandOptions.betaUploadArtifactTool) {
setBetaUploadArtifactToolEnabled(true);
}
if (commandOptions.betaSubagentTool) {
setBetaSubagentToolEnabled(true);
}
// Handle onboarding for TUI mode (headless: false) unless explicitly skipped
if (!initOptions.headless && !initOptions.skipOnboarding) {
const authConfig = loadAuthConfig();
Expand Down Expand Up @@ -383,6 +389,8 @@ export const services = {
gitAiIntegration: gitAiIntegrationService,
} as const;

export type ServicesType = typeof services;

// Export the service container for advanced usage
export { serviceContainer };

Expand Down
2 changes: 0 additions & 2 deletions extensions/cli/src/stream/streamChatResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,8 +457,6 @@ export async function streamChatResponse(
chatHistory = refreshChatHistoryFromService(chatHistory, isCompacting);
logger.debug("Starting conversation iteration");

logger.debug("debug1 streamChatResponse history", { chatHistory });

// Get system message once per iteration (can change based on tool permissions mode)
const systemMessage = await services.systemMessage.getSystemMessage(
services.toolPermissions.getState().currentMode,
Expand Down
Loading
Loading