Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/cerebras-16k-max-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---

Update Cerebras maxTokens from 8192 to 16384 for all models
5 changes: 5 additions & 0 deletions .changeset/gorgeous-carrots-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"kilo-code": minor
---

Add support for skills
10 changes: 5 additions & 5 deletions packages/types/src/providers/cerebras.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const cerebrasDefaultModelId: CerebrasModelId = "gpt-oss-120b"

export const cerebrasModels = {
"zai-glm-4.6": {
maxTokens: 8192, // Conservative default to avoid premature rate limiting (Cerebras reserves quota upfront)
maxTokens: 16384, // Conservative default to avoid premature rate limiting (Cerebras reserves quota upfront)
contextWindow: 131072,
supportsImages: false,
supportsPromptCache: false,
Expand All @@ -17,7 +17,7 @@ export const cerebrasModels = {
description: "Highly intelligent general purpose model with up to 1,000 tokens/s",
},
"qwen-3-235b-a22b-instruct-2507": {
maxTokens: 8192, // Conservative default to avoid premature rate limiting
maxTokens: 16384, // Conservative default to avoid premature rate limiting
contextWindow: 64000,
supportsImages: false,
supportsPromptCache: false,
Expand All @@ -27,7 +27,7 @@ export const cerebrasModels = {
description: "Intelligent model with ~1400 tokens/s",
},
"llama-3.3-70b": {
maxTokens: 8192, // Conservative default to avoid premature rate limiting
maxTokens: 16384, // Conservative default to avoid premature rate limiting
contextWindow: 64000,
supportsImages: false,
supportsPromptCache: false,
Expand All @@ -37,7 +37,7 @@ export const cerebrasModels = {
description: "Powerful model with ~2600 tokens/s",
},
"qwen-3-32b": {
maxTokens: 8192, // Conservative default to avoid premature rate limiting
maxTokens: 16384, // Conservative default to avoid premature rate limiting
contextWindow: 64000,
supportsImages: false,
supportsPromptCache: false,
Expand All @@ -47,7 +47,7 @@ export const cerebrasModels = {
description: "SOTA coding performance with ~2500 tokens/s",
},
"gpt-oss-120b": {
maxTokens: 8192, // Conservative default to avoid premature rate limiting
maxTokens: 16384, // Conservative default to avoid premature rate limiting
contextWindow: 64000,
supportsImages: false,
supportsPromptCache: false,
Expand Down
1 change: 1 addition & 0 deletions src/core/prompts/sections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export { getToolUseGuidelinesSection } from "./tool-use-guidelines"
export { getCapabilitiesSection } from "./capabilities"
export { getModesSection } from "./modes"
export { markdownFormattingSection } from "./markdown-formatting"
export { getSkillsSection } from "./skills"
71 changes: 71 additions & 0 deletions src/core/prompts/sections/skills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { SkillsManager, SkillMetadata } from "../../../services/skills/SkillsManager"

/**
* Get a display-friendly relative path for a skill.
* Converts absolute paths to relative paths to avoid leaking sensitive filesystem info.
*
* @param skill - The skill metadata
* @returns A relative path like ".kilocode/skills/name/SKILL.md" or "~/.kilocode/skills/name/SKILL.md"
*/
function getDisplayPath(skill: SkillMetadata): string {
const basePath = skill.source === "project" ? ".kilocode" : "~/.kilocode"
const skillsDir = skill.mode ? `skills-${skill.mode}` : "skills"
return `${basePath}/${skillsDir}/${skill.name}/SKILL.md`
}

/**
* Generate the skills section for the system prompt.
* Only includes skills relevant to the current mode.
* Format matches the modes section style.
*
* @param skillsManager - The SkillsManager instance
* @param currentMode - The current mode slug (e.g., 'code', 'architect')
*/
export async function getSkillsSection(
skillsManager: SkillsManager | undefined,
currentMode: string | undefined,
): Promise<string> {
if (!skillsManager || !currentMode) return ""

// Get skills filtered by current mode (with override resolution)
const skills = skillsManager.getSkillsForMode(currentMode)
if (skills.length === 0) return ""

// Separate generic and mode-specific skills for display
const genericSkills = skills.filter((s) => !s.mode)
const modeSpecificSkills = skills.filter((s) => s.mode === currentMode)

let skillsList = ""

if (modeSpecificSkills.length > 0) {
skillsList += modeSpecificSkills
.map(
(skill) =>
` * "${skill.name}" skill (${currentMode} mode) - ${skill.description} [${getDisplayPath(skill)}]`,
)
.join("\n")
}

if (genericSkills.length > 0) {
if (skillsList) skillsList += "\n"
skillsList += genericSkills
.map((skill) => ` * "${skill.name}" skill - ${skill.description} [${getDisplayPath(skill)}]`)
.join("\n")
}

return `====

AVAILABLE SKILLS

Skills are pre-packaged instructions for specific tasks. When a user request matches a skill description, read the full SKILL.md file to get detailed instructions.

- These are the currently available skills for "${currentMode}" mode:
${skillsList}

To use a skill:
1. Identify which skill matches the user's request based on the description
2. Use read_file to load the full SKILL.md file from the path shown in brackets
3. Follow the instructions in the skill file
4. Access any bundled files (scripts, references, assets) as needed
`
}
10 changes: 8 additions & 2 deletions src/core/prompts/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { formatLanguage } from "../../shared/language"
import { isEmpty } from "../../utils/object"
import { McpHub } from "../../services/mcp/McpHub"
import { CodeIndexManager } from "../../services/code-index/manager"
import { SkillsManager } from "../../services/skills/SkillsManager"

import { PromptVariables, loadSystemPromptFile } from "./sections/custom-system-prompt"

Expand All @@ -33,6 +34,7 @@ import {
getModesSection,
addCustomInstructions,
markdownFormattingSection,
getSkillsSection,
} from "./sections"
import { type ClineProviderState } from "../webview/ClineProvider" // kilocode_change

Expand Down Expand Up @@ -69,6 +71,7 @@ async function generatePrompt(
settings?: SystemPromptSettings,
todoList?: TodoItem[],
modelId?: string,
skillsManager?: SkillsManager,
clineProviderState?: ClineProviderState, // kilocode_change
): Promise<string> {
if (!context) {
Expand All @@ -92,7 +95,7 @@ async function generatePrompt(
// Determine the effective protocol (defaults to 'xml')
const effectiveProtocol = getEffectiveProtocol(settings?.toolProtocol)

const [modesSection, mcpServersSection] = await Promise.all([
const [modesSection, mcpServersSection, skillsSection] = await Promise.all([
getModesSection(context),
shouldIncludeMcp
? getMcpServersSection(
Expand All @@ -102,6 +105,7 @@ async function generatePrompt(
!isNativeProtocol(effectiveProtocol),
)
: Promise.resolve(""),
getSkillsSection(skillsManager, mode as string),
])

// Build tools catalog section only for XML protocol
Expand Down Expand Up @@ -137,7 +141,7 @@ ${mcpServersSection}
${getCapabilitiesSection(cwd, shouldIncludeMcp ? mcpHub : undefined)}

${modesSection}

${skillsSection ? `\n${skillsSection}` : ""}
${getRulesSection(cwd, settings, clineProviderState /* kilocode_change */)}

${getSystemInfoSection(cwd)}
Expand Down Expand Up @@ -175,6 +179,7 @@ export const SYSTEM_PROMPT = async (
settings?: SystemPromptSettings,
todoList?: TodoItem[],
modelId?: string,
skillsManager?: SkillsManager,
clineProviderState?: ClineProviderState, // kilocode_change
): Promise<string> => {
if (!context) {
Expand Down Expand Up @@ -251,6 +256,7 @@ ${customInstructions}`
settings,
todoList,
modelId,
skillsManager,
clineProviderState, // kilocode_change
)
}
5 changes: 2 additions & 3 deletions src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3773,9 +3773,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
},
undefined, // todoList
this.api.getModel().id,
// kilocode_change start
state,
// kilocode_change end
provider.getSkillsManager(),
state, // kilocode_change
)
})()
}
Expand Down
2 changes: 2 additions & 0 deletions src/core/task/__tests__/Task.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,8 @@ describe("Cline", () => {
getState: vi.fn().mockResolvedValue({
apiConfiguration: mockApiConfig,
}),
getMcpHub: vi.fn().mockReturnValue(undefined),
getSkillsManager: vi.fn().mockReturnValue(undefined),
say: vi.fn(),
postStateToWebview: vi.fn().mockResolvedValue(undefined),
postMessageToWebview: vi.fn().mockResolvedValue(undefined),
Expand Down
14 changes: 14 additions & 0 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import { CodeIndexManager } from "../../services/code-index/manager"
import type { IndexProgressUpdate } from "../../services/code-index/interfaces/manager"
import { MdmService } from "../../services/mdm/MdmService"
import { SessionManager } from "../../shared/kilocode/cli-sessions/core/SessionManager"
import { SkillsManager } from "../../services/skills/SkillsManager"

import { fileExistsAtPath } from "../../utils/fs"
import { setTtsEnabled, setTtsSpeed } from "../../utils/tts"
Expand Down Expand Up @@ -157,6 +158,7 @@ export class ClineProvider
private codeIndexManager?: CodeIndexManager
private _workspaceTracker?: WorkspaceTracker // workSpaceTracker read-only for access outside this class
protected mcpHub?: McpHub // Change from private to protected
protected skillsManager?: SkillsManager
private marketplaceManager: MarketplaceManager
private mdmService?: MdmService
private taskCreationCallback: (task: Task) => void
Expand Down Expand Up @@ -219,6 +221,12 @@ export class ClineProvider
this.log(`Failed to initialize MCP Hub: ${error}`)
})

// Initialize Skills Manager for skill discovery
this.skillsManager = new SkillsManager(this)
this.skillsManager.initialize().catch((error) => {
this.log(`Failed to initialize Skills Manager: ${error}`)
})

this.marketplaceManager = new MarketplaceManager(this.context, this.customModesManager)

// Forward <most> task events to the provider.
Expand Down Expand Up @@ -678,6 +686,8 @@ export class ClineProvider
this._workspaceTracker = undefined
await this.mcpHub?.unregisterClient()
this.mcpHub = undefined
await this.skillsManager?.dispose()
this.skillsManager = undefined
this.marketplaceManager?.cleanup()
this.customModesManager?.dispose()

Expand Down Expand Up @@ -2851,6 +2861,10 @@ ${prompt}
return this.mcpHub
}

public getSkillsManager(): SkillsManager | undefined {
return this.skillsManager
}

/**
* Check if the current state is compliant with MDM policy
* @returns true if compliant or no MDM policy exists, false if MDM policy exists and user is non-compliant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function makeProviderStub() {
rooIgnoreController: { getInstructions: () => undefined },
}),
getMcpHub: () => undefined,
getSkillsManager: () => undefined,
// State must enable browser tool and provide apiConfiguration
getState: async () => ({
apiConfiguration: {
Expand Down
9 changes: 4 additions & 5 deletions src/core/webview/generateSystemPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,10 @@ export const generateSystemPrompt = async (provider: ClineProvider, message: Web
toolProtocol,
isStealthModel: modelInfo?.isStealthModel,
},
// kilocode_change start
undefined,
undefined,
state,
// kilocode_change end
undefined, // todoList
undefined, // modelId
provider.getSkillsManager(),
state, // kilocode_change
)

return systemPrompt
Expand Down
Loading