Skip to content

Add metadata to create message #3832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 25, 2025
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/hot-lies-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"roo-cline": patch
---

Add metadata to create message
11 changes: 10 additions & 1 deletion src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,17 @@ export interface SingleCompletionHandler {
completePrompt(prompt: string): Promise<string>
}

export interface ApiHandlerCreateMessageMetadata {
mode?: string
taskId: string
}

export interface ApiHandler {
createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream
createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream

getModel(): { id: string; info: ModelInfo }

Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/anthropic-vertex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { getModelParams } from "../transform/model-params"

import { ANTHROPIC_DEFAULT_MAX_TOKENS } from "./constants"
import { BaseProvider } from "./base-provider"
import type { SingleCompletionHandler } from "../index"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"

// https://docs.anthropic.com/en/api/claude-on-vertex-ai
export class AnthropicVertexHandler extends BaseProvider implements SingleCompletionHandler {
Expand Down Expand Up @@ -50,7 +50,11 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple
}
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
let {
id,
info: { supportsPromptCache },
Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { getModelParams } from "../transform/model-params"

import { ANTHROPIC_DEFAULT_MAX_TOKENS } from "./constants"
import { BaseProvider } from "./base-provider"
import type { SingleCompletionHandler } from "../index"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"

export class AnthropicHandler extends BaseProvider implements SingleCompletionHandler {
private options: ApiHandlerOptions
Expand All @@ -34,7 +34,11 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
})
}

async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
let stream: AnthropicStream<Anthropic.Messages.RawMessageStreamEvent>
const cacheControl: CacheControlEphemeral = { type: "ephemeral" }
let { id: modelId, betas = [], maxTokens, temperature, reasoning: thinking } = this.getModel()
Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/base-openai-compatible-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ApiHandlerOptions, ModelInfo } from "../../shared/api"
import { ApiStream } from "../transform/stream"
import { convertToOpenAiMessages } from "../transform/openai-format"

import { SingleCompletionHandler } from "../index"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { DEFAULT_HEADERS } from "./constants"
import { BaseProvider } from "./base-provider"

Expand Down Expand Up @@ -60,7 +60,11 @@ export abstract class BaseOpenAiCompatibleProvider<ModelName extends string>
})
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const {
id: model,
info: { maxTokens: max_tokens },
Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/base-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ import { Anthropic } from "@anthropic-ai/sdk"

import { ModelInfo } from "../../shared/api"

import { ApiHandler } from "../index"
import type { ApiHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { ApiStream } from "../transform/stream"
import { countTokens } from "../../utils/countTokens"

/**
* Base class for API providers that implements common functionality.
*/
export abstract class BaseProvider implements ApiHandler {
abstract createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream
abstract createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream
abstract getModel(): { id: string; info: ModelInfo }

/**
Expand Down
10 changes: 7 additions & 3 deletions src/api/providers/bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
} from "@aws-sdk/client-bedrock-runtime"
import { fromIni } from "@aws-sdk/credential-providers"
import { Anthropic } from "@anthropic-ai/sdk"
import { SingleCompletionHandler } from "../"
import {
BedrockModelId,
ModelInfo as SharedModelInfo,
Expand All @@ -26,6 +25,7 @@ import { MultiPointStrategy } from "../transform/cache-strategy/multi-point-stra
import { ModelInfo as CacheModelInfo } from "../transform/cache-strategy/types"
import { AMAZON_BEDROCK_REGION_INFO } from "../../shared/aws_regions"
import { convertToBedrockConverseMessages as sharedConverter } from "../transform/bedrock-converse-format"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"

const BEDROCK_DEFAULT_TEMPERATURE = 0.3
const BEDROCK_MAX_TOKENS = 4096
Expand Down Expand Up @@ -189,7 +189,11 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
this.client = new BedrockRuntimeClient(clientConfig)
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
let modelConfig = this.getModel()
// Handle cross-region inference
const usePromptCache = Boolean(this.options.awsUsePromptCache && this.supportsAwsPromptCache(modelConfig))
Expand Down Expand Up @@ -769,7 +773,7 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
> = {
ACCESS_DENIED: {
patterns: ["access", "denied", "permission"],
messageTemplate: `You don't have access to the model specified.
messageTemplate: `You don't have access to the model specified.

Please verify:
1. Try cross-region inference if you're using a foundation model
Expand Down
16 changes: 12 additions & 4 deletions src/api/providers/fake-ai.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Anthropic } from "@anthropic-ai/sdk"
import { ApiHandler, SingleCompletionHandler } from ".."
import { ApiHandlerOptions, ModelInfo } from "../../shared/api"
import { ApiStream } from "../transform/stream"
import type { ApiHandler, SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"

interface FakeAI {
/**
Expand All @@ -18,7 +18,11 @@ interface FakeAI {
*/
removeFromCache?: () => void

createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream
createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream
getModel(): { id: string; info: ModelInfo }
countTokens(content: Array<Anthropic.Messages.ContentBlockParam>): Promise<number>
completePrompt(prompt: string): Promise<string>
Expand Down Expand Up @@ -52,8 +56,12 @@ export class FakeAIHandler implements ApiHandler, SingleCompletionHandler {
this.ai = cachedFakeAi
}

async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
yield* this.ai.createMessage(systemPrompt, messages)
async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
yield* this.ai.createMessage(systemPrompt, messages, metadata)
}

getModel(): { id: string; info: ModelInfo } {
Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { JWTInput } from "google-auth-library"
import { ApiHandlerOptions, ModelInfo, GeminiModelId, geminiDefaultModelId, geminiModels } from "../../shared/api"
import { safeJsonParse } from "../../shared/safeJsonParse"

import { SingleCompletionHandler } from "../index"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { convertAnthropicContentToGemini, convertAnthropicMessageToGemini } from "../transform/gemini-format"
import type { ApiStream } from "../transform/stream"
import { BaseProvider } from "./base-provider"
Expand Down Expand Up @@ -54,7 +54,11 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
: new GoogleGenAI({ apiKey })
}

async *createMessage(systemInstruction: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
async *createMessage(
systemInstruction: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const { id: model, thinkingConfig, maxOutputTokens, info } = this.getModel()

const contents = messages.map(convertAnthropicMessageToGemini)
Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/glama.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ApiStream } from "../transform/stream"
import { convertToOpenAiMessages } from "../transform/openai-format"
import { addCacheBreakpoints } from "../transform/caching/anthropic"

import { SingleCompletionHandler } from "../index"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { RouterProvider } from "./router-provider"

const GLAMA_DEFAULT_TEMPERATURE = 0
Expand All @@ -33,7 +33,11 @@ export class GlamaHandler extends RouterProvider implements SingleCompletionHand
})
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const { id: modelId, info } = await this.fetchModel()

const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
Expand Down
9 changes: 7 additions & 2 deletions src/api/providers/human-relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as vscode from "vscode"
import { ModelInfo } from "../../shared/api"
import { getCommand } from "../../utils/commands"
import { ApiStream } from "../transform/stream"
import { ApiHandler, SingleCompletionHandler } from "../index"
import type { ApiHandler, SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
/**
* Human Relay API processor
* This processor does not directly call the API, but interacts with the model through human operations copy and paste.
Expand All @@ -18,8 +18,13 @@ export class HumanRelayHandler implements ApiHandler, SingleCompletionHandler {
* Create a message processing flow, display a dialog box to request human assistance
* @param systemPrompt System prompt words
* @param messages Message list
* @param metadata Optional metadata
*/
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
// Get the most recent user message
const latestMessage = messages[messages.length - 1]

Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/litellm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Anthropic } from "@anthropic-ai/sdk" // Keep for type usage only
import { ApiHandlerOptions, litellmDefaultModelId, litellmDefaultModelInfo } from "../../shared/api"
import { ApiStream, ApiStreamUsageChunk } from "../transform/stream"
import { convertToOpenAiMessages } from "../transform/openai-format"
import { SingleCompletionHandler } from "../index"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { RouterProvider } from "./router-provider"

/**
Expand All @@ -26,7 +26,11 @@ export class LiteLLMHandler extends RouterProvider implements SingleCompletionHa
})
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const { id: modelId, info } = await this.fetchModel()

const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/lmstudio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { Anthropic } from "@anthropic-ai/sdk"
import OpenAI from "openai"
import axios from "axios"

import { SingleCompletionHandler } from "../"
import { ApiHandlerOptions, ModelInfo, openAiModelInfoSaneDefaults } from "../../shared/api"
import { convertToOpenAiMessages } from "../transform/openai-format"
import { ApiStream } from "../transform/stream"
import { BaseProvider } from "./base-provider"
import { XmlMatcher } from "../../utils/xml-matcher"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"

const LMSTUDIO_DEFAULT_TEMPERATURE = 0

Expand All @@ -24,7 +24,11 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan
})
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
{ role: "system", content: systemPrompt },
...convertToOpenAiMessages(messages),
Expand Down
10 changes: 8 additions & 2 deletions src/api/providers/mistral.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Anthropic } from "@anthropic-ai/sdk"
import { Mistral } from "@mistralai/mistralai"
import { SingleCompletionHandler } from "../"
import { ApiHandlerOptions, mistralDefaultModelId, MistralModelId, mistralModels, ModelInfo } from "../../shared/api"
import { convertToMistralMessages } from "../transform/mistral-format"
import { ApiStream } from "../transform/stream"
import { BaseProvider } from "./base-provider"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"

const MISTRAL_DEFAULT_TEMPERATURE = 0

Expand Down Expand Up @@ -41,7 +41,13 @@ export class MistralHandler extends BaseProvider implements SingleCompletionHand
return "https://api.mistral.ai"
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const { id: model } = this.getModel()

const response = await this.client.chat.stream({
model: this.options.apiModelId || mistralDefaultModelId,
messages: [{ role: "system", content: systemPrompt }, ...convertToMistralMessages(messages)],
Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/ollama.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
import OpenAI from "openai"
import axios from "axios"

import { SingleCompletionHandler } from "../"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { ApiHandlerOptions, ModelInfo, openAiModelInfoSaneDefaults } from "../../shared/api"
import { convertToOpenAiMessages } from "../transform/openai-format"
import { convertToR1Format } from "../transform/r1-format"
Expand All @@ -27,7 +27,11 @@ export class OllamaHandler extends BaseProvider implements SingleCompletionHandl
})
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const modelId = this.getModel().id
const useR1Format = modelId.toLowerCase().includes("deepseek-r1")
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/openai-native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { convertToOpenAiMessages } from "../transform/openai-format"
import { ApiStream } from "../transform/stream"
import { getModelParams } from "../transform/model-params"

import type { SingleCompletionHandler } from "../index"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { BaseProvider } from "./base-provider"

const OPENAI_NATIVE_DEFAULT_TEMPERATURE = 0
Expand All @@ -33,7 +33,11 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
this.client = new OpenAI({ baseURL: this.options.openAiNativeBaseUrl, apiKey })
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const model = this.getModel()
let id: "o3-mini" | "o3" | "o4-mini" | undefined

Expand Down
8 changes: 6 additions & 2 deletions src/api/providers/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { ApiStream, ApiStreamUsageChunk } from "../transform/stream"
import { getModelParams } from "../transform/model-params"

import { DEFAULT_HEADERS, DEEP_SEEK_DEFAULT_TEMPERATURE } from "./constants"
import type { SingleCompletionHandler } from "../index"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { BaseProvider } from "./base-provider"

export const AZURE_AI_INFERENCE_PATH = "/models/chat/completions"
Expand Down Expand Up @@ -71,7 +71,11 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
}
}

override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
override async *createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream {
const { info: modelInfo, reasoning } = this.getModel()
const modelUrl = this.options.openAiBaseUrl ?? ""
const modelId = this.options.openAiModelId ?? ""
Expand Down
Loading
Loading