Skip to content

Commit 8d3053b

Browse files
committed
feat: add stop token option to API configuration and update debug output settings
1 parent fe44d7d commit 8d3053b

File tree

6 files changed

+48
-48
lines changed

6 files changed

+48
-48
lines changed

package.json

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -270,16 +270,10 @@
270270
},
271271
"description": "Settings for VSCode Language Model API"
272272
},
273-
"roo-cline.debug": {
274-
"type": "object",
275-
"description": "Debug settings for Roo Code",
276-
"properties": {
277-
"mistral": {
278-
"type": "boolean",
279-
"default": false,
280-
"description": "Enable debug output channel for Mistral API interactions"
281-
}
282-
}
273+
"roo-cline.debug.mistral": {
274+
"type": "boolean",
275+
"default": false,
276+
"description": "Enable debug output channel 'Roo Code Mistral' for Mistral API interactions"
283277
}
284278
}
285279
}

src/api/providers/mistral.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,31 @@ export class MistralHandler implements ApiHandler {
4242
const baseUrl = this.getBaseUrl()
4343
this.logDebug(`MistralHandler using baseUrl: ${baseUrl}`)
4444

45-
const logger = this.enableDebugOutput
46-
? {
47-
group: (message: string) => this.logDebug(`[Mistral Group] ${message}`),
48-
groupEnd: () => this.logDebug(`[Mistral GroupEnd]`),
49-
log: (...args: any[]) =>
50-
this.logDebug(
51-
`[Mistral Log] ${args
52-
.map((arg) => (typeof arg === "object" ? JSON.stringify(arg, null, 2) : arg))
53-
.join(" ")}`,
54-
),
45+
const logger = {
46+
group: (message: string) => {
47+
if (this.enableDebugOutput && this.outputChannel) {
48+
this.outputChannel.appendLine(`[Mistral SDK] Group: ${message}`)
5549
}
56-
: undefined
50+
},
51+
groupEnd: () => {
52+
if (this.enableDebugOutput && this.outputChannel) {
53+
this.outputChannel.appendLine(`[Mistral SDK] GroupEnd`)
54+
}
55+
},
56+
log: (...args: any[]) => {
57+
if (this.enableDebugOutput && this.outputChannel) {
58+
const formattedArgs = args
59+
.map((arg) => (typeof arg === "object" ? JSON.stringify(arg, null, 2) : arg))
60+
.join(" ")
61+
this.outputChannel.appendLine(`[Mistral SDK] ${formattedArgs}`)
62+
}
63+
},
64+
}
5765

5866
this.client = new Mistral({
5967
serverURL: baseUrl,
6068
apiKey: this.options.mistralApiKey,
61-
debugLogger: logger,
69+
debugLogger: this.enableDebugOutput ? logger : undefined,
6270
})
6371
}
6472

@@ -87,6 +95,7 @@ export class MistralHandler implements ApiHandler {
8795
messages: [{ role: "system", content: systemPrompt }, ...convertToMistralMessages(messages)],
8896
temperature: this.options?.modelTemperature ?? MISTRAL_DEFAULT_TEMPERATURE,
8997
...(this.options?.mistralModelStreamingEnabled === true && { stream: true }),
98+
...(this.options?.stopToken?.trim() && { stop: [this.options.stopToken] }),
9099
})
91100

92101
let completeContent = ""

src/core/Cline.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,6 @@ type UserContent = Array<
7474
>
7575

7676
export class Cline {
77-
private static readonly outputChannelName = "Roo Code Stream Output"
78-
private static sharedOutputChannel: vscode.OutputChannel | undefined
79-
// private readonly enableStreamDebug: boolean
80-
// private readonly outputChannel?: vscode.OutputChannel
81-
8277
readonly taskId: string
8378
api: ApiHandler
8479
private terminalManager: TerminalManager
@@ -135,16 +130,6 @@ export class Cline {
135130
historyItem?: HistoryItem | undefined,
136131
experiments?: Record<string, boolean>,
137132
) {
138-
// const config = vscode.workspace.getConfiguration("roo-cline")
139-
// this.enableStreamDebug = config.get<boolean>("enableApiStreamDebugOutput", false)
140-
141-
// if (this.enableStreamDebug) {
142-
// if (!Cline.sharedOutputChannel) {
143-
// Cline.sharedOutputChannel = vscode.window.createOutputChannel(Cline.outputChannelName)
144-
// }
145-
// this.outputChannel = Cline.sharedOutputChannel
146-
// }
147-
148133
if (!task && !images && !historyItem) {
149134
throw new Error("Either historyItem or task/images must be provided")
150135
}
@@ -175,12 +160,6 @@ export class Cline {
175160
}
176161
}
177162

178-
// private logStreamDebug(message: string) {
179-
// if (this.enableStreamDebug && this.outputChannel) {
180-
// this.outputChannel.appendLine(`[Stream Debug] ${message}`)
181-
// }
182-
// }
183-
184163
// Add method to update diffStrategy
185164
async updateDiffStrategy(experimentalDiffStrategy?: boolean) {
186165
// If not provided, get from current state
@@ -986,17 +965,12 @@ export class Cline {
986965
const iterator = stream[Symbol.asyncIterator]()
987966

988967
try {
989-
this.logStreamDebug(
990-
`Starting API request - Previous index: ${previousApiReqIndex}, Retry attempt: ${retryAttempt}`,
991-
)
992968
// awaiting first chunk to see if it will throw an error
993969
this.isWaitingForFirstChunk = true
994970
const firstChunk = await iterator.next()
995-
this.logStreamDebug(`Received first chunk: ${JSON.stringify(firstChunk.value)}`)
996971
yield firstChunk.value
997972
this.isWaitingForFirstChunk = false
998973
} catch (error) {
999-
this.logStreamDebug(`Error on first chunk: ${error}`)
1000974
// note that this api_req_failed ask is unique in that we only present this option if the api hasn't streamed any content yet (ie it fails on the first chunk due), as it would allow them to hit a retry button. However if the api failed mid-stream, it could be in any arbitrary state where some tools may have executed, so that error is handled differently and requires cancelling the task entirely.
1001975
if (alwaysApproveResubmit) {
1002976
const errorMsg = error.message ?? "Unknown error"

src/core/webview/ClineProvider.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ type GlobalStateKey =
127127
| "requestyModelInfo"
128128
| "unboundModelInfo"
129129
| "modelTemperature"
130+
| "stopToken"
130131
| "mistralCodestralUrl"
131132
| "mistralModelStreamingEnabled"
132133
| "maxOpenTabsContext"
@@ -1678,6 +1679,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
16781679
requestyModelId,
16791680
requestyModelInfo,
16801681
modelTemperature,
1682+
stopToken,
16811683
} = apiConfiguration
16821684
await Promise.all([
16831685
this.updateGlobalState("apiProvider", apiProvider),
@@ -1726,6 +1728,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
17261728
this.updateGlobalState("requestyModelId", requestyModelId),
17271729
this.updateGlobalState("requestyModelInfo", requestyModelInfo),
17281730
this.updateGlobalState("modelTemperature", modelTemperature),
1731+
this.updateGlobalState("stopToken", stopToken),
17291732
])
17301733
if (this.cline) {
17311734
this.cline.api = buildApiHandler(apiConfiguration)
@@ -2609,6 +2612,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
26092612
requestyModelId,
26102613
requestyModelInfo,
26112614
modelTemperature,
2615+
stopToken,
26122616
maxOpenTabsContext,
26132617
] = await Promise.all([
26142618
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
@@ -2692,6 +2696,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
26922696
this.getGlobalState("requestyModelId") as Promise<string | undefined>,
26932697
this.getGlobalState("requestyModelInfo") as Promise<ModelInfo | undefined>,
26942698
this.getGlobalState("modelTemperature") as Promise<number | undefined>,
2699+
this.getGlobalState("stopToken") as Promise<string | undefined>,
26952700
this.getGlobalState("maxOpenTabsContext") as Promise<number | undefined>,
26962701
])
26972702

@@ -2757,6 +2762,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
27572762
requestyModelId,
27582763
requestyModelInfo,
27592764
modelTemperature,
2765+
stopToken,
27602766
},
27612767
lastShownAnnouncementId,
27622768
customInstructions,

src/shared/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export interface ApiHandlerOptions {
6868
requestyModelId?: string
6969
requestyModelInfo?: ModelInfo
7070
modelTemperature?: number
71+
stopToken?: string
7172
}
7273

7374
export type ApiConfiguration = ApiHandlerOptions & {

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,22 @@ const ApiOptions = ({
348348
</div>
349349
)}
350350

351+
<VSCodeTextField
352+
value={apiConfiguration?.stopToken}
353+
style={{ width: "100%", marginTop: "10px" }}
354+
onInput={handleInputChange("stopToken")}
355+
placeholder="Enter stop token (optional)">
356+
<span style={{ fontWeight: 500 }}>Optional: Stop Token e.g. \n\\n\</span>
357+
</VSCodeTextField>
358+
<p
359+
style={{
360+
fontSize: "12px",
361+
marginTop: 3,
362+
color: "var(--vscode-descriptionForeground)",
363+
}}>
364+
Optional token to stop generation when encountered
365+
</p>
366+
351367
<p>
352368
<div style={{ display: "flex", alignItems: "center" }}>
353369
<Checkbox

0 commit comments

Comments
 (0)