Merge branch 'main' of https://github.com/RooVetGit/Roo-Code into fix-editorutils

This commit is contained in:
Nissa Seru 2025-02-02 03:00:25 -05:00
commit fb3f60703e
5 changed files with 175 additions and 116 deletions

View file

@ -0,0 +1,5 @@
---
"roo-cline": patch
---
Visual cleanup to the list of modes on the prompts tab

View file

@ -14,8 +14,7 @@ jobs:
uses: Ilshidur/action-discord@master
with:
args: |
🚀 **New Pull Request Opened!**
📝 **Title:** ${{ github.event.pull_request.title }}
🚀 **New PR:** ${{ github.event.pull_request.title }}
🔗 <${{ github.event.pull_request.html_url }}>
👤 **Author:** ${{ github.event.pull_request.user.login }}
env:

View file

@ -153,11 +153,35 @@ describe("OpenAiNativeHandler", () => {
expect(mockCreate).toHaveBeenCalledWith({
model: "o1",
messages: [
{ role: "developer", content: systemPrompt },
{ role: "developer", content: "Formatting re-enabled\n" + systemPrompt },
{ role: "user", content: "Hello!" },
],
})
})
it("should handle o3-mini model family correctly", async () => {
handler = new OpenAiNativeHandler({
...mockOptions,
apiModelId: "o3-mini",
})
const stream = handler.createMessage(systemPrompt, messages)
const chunks: any[] = []
for await (const chunk of stream) {
chunks.push(chunk)
}
expect(mockCreate).toHaveBeenCalledWith({
model: "o3-mini",
messages: [
{ role: "developer", content: "Formatting re-enabled\n" + systemPrompt },
{ role: "user", content: "Hello!" },
],
stream: true,
stream_options: { include_usage: true },
reasoning_effort: "medium",
})
})
})
describe("streaming models", () => {

View file

@ -24,88 +24,111 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
const modelId = this.getModel().id
switch (modelId) {
case "o1":
case "o1-preview":
case "o1-mini": {
// o1-preview and o1-mini don't support streaming, non-1 temp, or system prompt
// o1 doesnt support streaming or non-1 temp but does support a developer prompt
const response = await this.client.chat.completions.create({
model: modelId,
messages: [
{ role: modelId === "o1" ? "developer" : "user", content: systemPrompt },
...convertToOpenAiMessages(messages),
],
})
if (modelId.startsWith("o1")) {
yield* this.handleO1FamilyMessage(modelId, systemPrompt, messages)
return
}
if (modelId.startsWith("o3-mini")) {
yield* this.handleO3FamilyMessage(modelId, systemPrompt, messages)
return
}
yield* this.handleDefaultModelMessage(modelId, systemPrompt, messages)
}
private async *handleO1FamilyMessage(
modelId: string,
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[]
): ApiStream {
// o1 supports developer prompt with formatting
// o1-preview and o1-mini only support user messages
const isOriginalO1 = modelId === "o1"
const response = await this.client.chat.completions.create({
model: modelId,
messages: [
{
role: isOriginalO1 ? "developer" : "user",
content: isOriginalO1 ? `Formatting re-enabled\n${systemPrompt}` : systemPrompt,
},
...convertToOpenAiMessages(messages),
],
})
yield* this.yieldResponseData(response)
}
private async *handleO3FamilyMessage(
modelId: string,
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[]
): ApiStream {
const stream = await this.client.chat.completions.create({
model: "o3-mini",
messages: [
{
role: "developer",
content: `Formatting re-enabled\n${systemPrompt}`,
},
...convertToOpenAiMessages(messages),
],
stream: true,
stream_options: { include_usage: true },
reasoning_effort: this.getModel().info.reasoningEffort,
})
yield* this.handleStreamResponse(stream)
}
private async *handleDefaultModelMessage(
modelId: string,
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[]
): ApiStream {
const stream = await this.client.chat.completions.create({
model: modelId,
temperature: 0,
messages: [{ role: "system", content: systemPrompt }, ...convertToOpenAiMessages(messages)],
stream: true,
stream_options: { include_usage: true },
})
yield* this.handleStreamResponse(stream)
}
private async *yieldResponseData(
response: OpenAI.Chat.Completions.ChatCompletion
): ApiStream {
yield {
type: "text",
text: response.choices[0]?.message.content || "",
}
yield {
type: "usage",
inputTokens: response.usage?.prompt_tokens || 0,
outputTokens: response.usage?.completion_tokens || 0,
}
}
private async *handleStreamResponse(
stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>
): ApiStream {
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta
if (delta?.content) {
yield {
type: "text",
text: response.choices[0]?.message.content || "",
text: delta.content,
}
}
if (chunk.usage) {
yield {
type: "usage",
inputTokens: response.usage?.prompt_tokens || 0,
outputTokens: response.usage?.completion_tokens || 0,
}
break
}
case "o3-mini":
case "o3-mini-low":
case "o3-mini-high": {
const stream = await this.client.chat.completions.create({
model: "o3-mini",
messages: [{ role: "developer", content: systemPrompt }, ...convertToOpenAiMessages(messages)],
stream: true,
stream_options: { include_usage: true },
reasoning_effort: this.getModel().info.reasoningEffort,
})
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta
if (delta?.content) {
yield {
type: "text",
text: delta.content,
}
}
// contains a null value except for the last chunk which contains the token usage statistics for the entire request
if (chunk.usage) {
yield {
type: "usage",
inputTokens: chunk.usage.prompt_tokens || 0,
outputTokens: chunk.usage.completion_tokens || 0,
}
}
}
break
}
default: {
const stream = await this.client.chat.completions.create({
model: this.getModel().id,
// max_completion_tokens: this.getModel().info.maxTokens,
temperature: 0,
messages: [{ role: "system", content: systemPrompt }, ...convertToOpenAiMessages(messages)],
stream: true,
stream_options: { include_usage: true },
})
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta
if (delta?.content) {
yield {
type: "text",
text: delta.content,
}
}
// contains a null value except for the last chunk which contains the token usage statistics for the entire request
if (chunk.usage) {
yield {
type: "usage",
inputTokens: chunk.usage.prompt_tokens || 0,
outputTokens: chunk.usage.completion_tokens || 0,
}
}
inputTokens: chunk.usage.prompt_tokens || 0,
outputTokens: chunk.usage.completion_tokens || 0,
}
}
}
@ -125,32 +148,12 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
const modelId = this.getModel().id
let requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming
switch (modelId) {
case "o1":
case "o1-preview":
case "o1-mini":
// o1 doesn't support non-1 temp
requestOptions = {
model: modelId,
messages: [{ role: "user", content: prompt }],
}
break
case "o3-mini":
case "o3-mini-low":
case "o3-mini-high":
// o3 doesn't support non-1 temp
requestOptions = {
model: "o3-mini",
messages: [{ role: "user", content: prompt }],
reasoning_effort: this.getModel().info.reasoningEffort,
}
break
default:
requestOptions = {
model: modelId,
messages: [{ role: "user", content: prompt }],
temperature: 0,
}
if (modelId.startsWith("o1")) {
requestOptions = this.getO1CompletionOptions(modelId, prompt)
} else if (modelId.startsWith("o3-mini")) {
requestOptions = this.getO3CompletionOptions(modelId, prompt)
} else {
requestOptions = this.getDefaultCompletionOptions(modelId, prompt)
}
const response = await this.client.chat.completions.create(requestOptions)
@ -162,4 +165,36 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
throw error
}
}
private getO1CompletionOptions(
modelId: string,
prompt: string
): OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming {
return {
model: modelId,
messages: [{ role: "user", content: prompt }],
}
}
private getO3CompletionOptions(
modelId: string,
prompt: string
): OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming {
return {
model: "o3-mini",
messages: [{ role: "user", content: prompt }],
reasoning_effort: this.getModel().info.reasoningEffort,
}
}
private getDefaultCompletionOptions(
modelId: string,
prompt: string
): OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming {
return {
model: modelId,
messages: [{ role: "user", content: prompt }],
temperature: 0,
}
}
}

View file

@ -472,13 +472,11 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
<div
style={{
display: "flex",
gap: "16px",
gap: "8px",
alignItems: "center",
marginBottom: "12px",
overflowX: "auto",
flexWrap: "nowrap",
paddingBottom: "4px",
paddingRight: "20px",
flexWrap: "wrap",
padding: "4px 0",
}}>
{modes.map((modeConfig) => {
const isActive = mode === modeConfig.slug
@ -859,13 +857,11 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
<div
style={{
display: "flex",
gap: "16px",
gap: "8px",
alignItems: "center",
marginBottom: "12px",
overflowX: "auto",
flexWrap: "nowrap",
paddingBottom: "4px",
paddingRight: "20px",
flexWrap: "wrap",
padding: "4px 0",
}}>
{Object.keys(supportPrompt.default).map((type) => (
<button