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
11 changes: 11 additions & 0 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ export const globalSettingsSchema = z.object({
autoCondenseContextPercent: z.number().optional(),
maxConcurrentFileReads: z.number().optional(),

/**
* Whether to include current time in the environment details
* @default true
*/
includeCurrentTime: z.boolean().optional(),
/**
* Whether to include current cost in the environment details
* @default true
*/
includeCurrentCost: z.boolean().optional(),

/**
* Whether to include diagnostic messages (errors, warnings) in tool outputs
* @default true
Expand Down
35 changes: 21 additions & 14 deletions src/core/environment/getEnvironmentDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,21 +190,28 @@ export async function getEnvironmentDetails(cline: Task, includeFileDetails: boo
details += terminalDetails
}

// Add current time information with timezone.
const now = new Date()

const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
const timeZoneOffset = -now.getTimezoneOffset() / 60 // Convert to hours and invert sign to match conventional notation
const timeZoneOffsetHours = Math.floor(Math.abs(timeZoneOffset))
const timeZoneOffsetMinutes = Math.abs(Math.round((Math.abs(timeZoneOffset) - timeZoneOffsetHours) * 60))
const timeZoneOffsetStr = `${timeZoneOffset >= 0 ? "+" : "-"}${timeZoneOffsetHours}:${timeZoneOffsetMinutes.toString().padStart(2, "0")}`
details += `\n\n# Current Time\nCurrent time in ISO 8601 UTC format: ${now.toISOString()}\nUser time zone: ${timeZone}, UTC${timeZoneOffsetStr}`

// Add context tokens information.
const { contextTokens, totalCost } = getApiMetrics(cline.clineMessages)
const { id: modelId } = cline.api.getModel()
// Get settings for time and cost display
const { includeCurrentTime = true, includeCurrentCost = true } = state ?? {}

// Add current time information with timezone (if enabled).
if (includeCurrentTime) {
const now = new Date()

const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
const timeZoneOffset = -now.getTimezoneOffset() / 60 // Convert to hours and invert sign to match conventional notation
const timeZoneOffsetHours = Math.floor(Math.abs(timeZoneOffset))
const timeZoneOffsetMinutes = Math.abs(Math.round((Math.abs(timeZoneOffset) - timeZoneOffsetHours) * 60))
const timeZoneOffsetStr = `${timeZoneOffset >= 0 ? "+" : "-"}${timeZoneOffsetHours}:${timeZoneOffsetMinutes.toString().padStart(2, "0")}`
details += `\n\n# Current Time\nCurrent time in ISO 8601 UTC format: ${now.toISOString()}\nUser time zone: ${timeZone}, UTC${timeZoneOffsetStr}`
}

details += `\n\n# Current Cost\n${totalCost !== null ? `$${totalCost.toFixed(2)}` : "(Not available)"}`
// Add context tokens information (if enabled).
if (includeCurrentCost) {
const { totalCost } = getApiMetrics(cline.clineMessages)
details += `\n\n# Current Cost\n${totalCost !== null ? `$${totalCost.toFixed(2)}` : "(Not available)"}`
}

const { id: modelId } = cline.api.getModel()

// Add current mode and any mode-specific warnings.
const {
Expand Down
6 changes: 6 additions & 0 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,8 @@ export class ClineProvider
includeDiagnosticMessages,
maxDiagnosticMessages,
includeTaskHistoryInEnhance,
includeCurrentTime,
includeCurrentCost,
taskSyncEnabled,
remoteControlEnabled,
openRouterImageApiKey,
Expand Down Expand Up @@ -1961,6 +1963,8 @@ export class ClineProvider
includeDiagnosticMessages: includeDiagnosticMessages ?? true,
maxDiagnosticMessages: maxDiagnosticMessages ?? 50,
includeTaskHistoryInEnhance: includeTaskHistoryInEnhance ?? true,
includeCurrentTime: includeCurrentTime ?? true,
includeCurrentCost: includeCurrentCost ?? true,
taskSyncEnabled,
remoteControlEnabled,
openRouterImageApiKey,
Expand Down Expand Up @@ -2173,6 +2177,8 @@ export class ClineProvider
includeDiagnosticMessages: stateValues.includeDiagnosticMessages ?? true,
maxDiagnosticMessages: stateValues.maxDiagnosticMessages ?? 50,
includeTaskHistoryInEnhance: stateValues.includeTaskHistoryInEnhance ?? true,
includeCurrentTime: stateValues.includeCurrentTime ?? true,
includeCurrentCost: stateValues.includeCurrentCost ?? true,
taskSyncEnabled,
remoteControlEnabled: (() => {
try {
Expand Down
8 changes: 8 additions & 0 deletions src/core/webview/webviewMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1658,6 +1658,14 @@ export const webviewMessageHandler = async (
await updateGlobalState("includeDiagnosticMessages", includeValue)
await provider.postStateToWebview()
break
case "includeCurrentTime":
await updateGlobalState("includeCurrentTime", message.bool ?? true)
await provider.postStateToWebview()
break
case "includeCurrentCost":
await updateGlobalState("includeCurrentCost", message.bool ?? true)
await provider.postStateToWebview()
break
case "maxDiagnosticMessages":
await updateGlobalState("maxDiagnosticMessages", message.value ?? 50)
await provider.postStateToWebview()
Expand Down
2 changes: 2 additions & 0 deletions src/shared/ExtensionMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ export type ExtensionState = Pick<
| "openRouterImageGenerationSelectedModel"
| "includeTaskHistoryInEnhance"
| "reasoningBlockCollapsed"
| "includeCurrentTime"
| "includeCurrentCost"
> & {
version: string
clineMessages: ClineMessage[]
Expand Down
2 changes: 2 additions & 0 deletions src/shared/WebviewMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ export interface WebviewMessage {
| "maxConcurrentFileReads"
| "includeDiagnosticMessages"
| "maxDiagnosticMessages"
| "includeCurrentTime"
| "includeCurrentCost"
| "searchFiles"
| "toggleApiConfigPin"
| "setHistoryPreviewCollapsed"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type ContextManagementSettingsProps = HTMLAttributes<HTMLDivElement> & {
includeDiagnosticMessages?: boolean
maxDiagnosticMessages?: number
writeDelayMs: number
includeCurrentTime?: boolean
includeCurrentCost?: boolean
setCachedStateField: SetCachedStateField<
| "autoCondenseContext"
| "autoCondenseContextPercent"
Expand All @@ -41,6 +43,8 @@ type ContextManagementSettingsProps = HTMLAttributes<HTMLDivElement> & {
| "includeDiagnosticMessages"
| "maxDiagnosticMessages"
| "writeDelayMs"
| "includeCurrentTime"
| "includeCurrentCost"
>
}

Expand All @@ -60,6 +64,8 @@ export const ContextManagementSettings = ({
includeDiagnosticMessages,
maxDiagnosticMessages,
writeDelayMs,
includeCurrentTime,
includeCurrentCost,
className,
...props
}: ContextManagementSettingsProps) => {
Expand Down Expand Up @@ -356,6 +362,34 @@ export const ContextManagementSettings = ({
{t("settings:contextManagement.diagnostics.delayAfterWrite.description")}
</div>
</div>

<div>
<VSCodeCheckbox
checked={includeCurrentTime}
onChange={(e: any) => setCachedStateField("includeCurrentTime", e.target.checked)}
data-testid="include-current-time-checkbox">
<label className="block font-medium mb-1">
{t("settings:contextManagement.includeCurrentTime.label")}
</label>
</VSCodeCheckbox>
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-3">
{t("settings:contextManagement.includeCurrentTime.description")}
</div>
</div>

<div>
<VSCodeCheckbox
checked={includeCurrentCost}
onChange={(e: any) => setCachedStateField("includeCurrentCost", e.target.checked)}
data-testid="include-current-cost-checkbox">
<label className="block font-medium mb-1">
{t("settings:contextManagement.includeCurrentCost.label")}
</label>
</VSCodeCheckbox>
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-3">
{t("settings:contextManagement.includeCurrentCost.description")}
</div>
</div>
</Section>
<Section className="pt-2">
<VSCodeCheckbox
Expand Down
6 changes: 6 additions & 0 deletions webview-ui/src/components/settings/SettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
openRouterImageApiKey,
openRouterImageGenerationSelectedModel,
reasoningBlockCollapsed,
includeCurrentTime,
includeCurrentCost,
} = cachedState

const apiConfiguration = useMemo(() => cachedState.apiConfiguration ?? {}, [cachedState.apiConfiguration])
Expand Down Expand Up @@ -386,6 +388,8 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
vscode.postMessage({ type: "updateSupportPrompt", values: customSupportPrompts || {} })
vscode.postMessage({ type: "includeTaskHistoryInEnhance", bool: includeTaskHistoryInEnhance ?? true })
vscode.postMessage({ type: "setReasoningBlockCollapsed", bool: reasoningBlockCollapsed ?? true })
vscode.postMessage({ type: "includeCurrentTime", bool: includeCurrentTime ?? true })
vscode.postMessage({ type: "includeCurrentCost", bool: includeCurrentCost ?? true })
vscode.postMessage({ type: "upsertApiConfiguration", text: currentApiConfigName, apiConfiguration })
vscode.postMessage({ type: "telemetrySetting", text: telemetrySetting })
vscode.postMessage({ type: "profileThresholds", values: profileThresholds })
Expand Down Expand Up @@ -747,6 +751,8 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
includeDiagnosticMessages={includeDiagnosticMessages}
maxDiagnosticMessages={maxDiagnosticMessages}
writeDelayMs={writeDelayMs}
includeCurrentTime={includeCurrentTime}
includeCurrentCost={includeCurrentCost}
setCachedStateField={setCachedStateField}
/>
)}
Expand Down
20 changes: 20 additions & 0 deletions webview-ui/src/context/ExtensionStateContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ export interface ExtensionStateContextType extends ExtensionState {
setMaxDiagnosticMessages: (value: number) => void
includeTaskHistoryInEnhance?: boolean
setIncludeTaskHistoryInEnhance: (value: boolean) => void
includeCurrentTime?: boolean
setIncludeCurrentTime: (value: boolean) => void
includeCurrentCost?: boolean
setIncludeCurrentCost: (value: boolean) => void
}

export const ExtensionStateContext = createContext<ExtensionStateContextType | undefined>(undefined)
Expand Down Expand Up @@ -270,6 +274,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
maxDiagnosticMessages: 50,
openRouterImageApiKey: "",
openRouterImageGenerationSelectedModel: "",
includeCurrentTime: true,
includeCurrentCost: true,
})

const [didHydrateState, setDidHydrateState] = useState(false)
Expand All @@ -290,6 +296,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
})
const [includeTaskHistoryInEnhance, setIncludeTaskHistoryInEnhance] = useState(true)
const [prevCloudIsAuthenticated, setPrevCloudIsAuthenticated] = useState(false)
const [includeCurrentTime, setIncludeCurrentTime] = useState(true)
const [includeCurrentCost, setIncludeCurrentCost] = useState(true)

const setListApiConfigMeta = useCallback(
(value: ProviderSettingsEntry[]) => setState((prevState) => ({ ...prevState, listApiConfigMeta: value })),
Expand Down Expand Up @@ -327,6 +335,14 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
if ((newState as any).includeTaskHistoryInEnhance !== undefined) {
setIncludeTaskHistoryInEnhance((newState as any).includeTaskHistoryInEnhance)
}
// Update includeCurrentTime if present in state message
if ((newState as any).includeCurrentTime !== undefined) {
setIncludeCurrentTime((newState as any).includeCurrentTime)
}
// Update includeCurrentCost if present in state message
if ((newState as any).includeCurrentCost !== undefined) {
setIncludeCurrentCost((newState as any).includeCurrentCost)
}
// Handle marketplace data if present in state message
if (newState.marketplaceItems !== undefined) {
setMarketplaceItems(newState.marketplaceItems)
Expand Down Expand Up @@ -575,6 +591,10 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
},
includeTaskHistoryInEnhance,
setIncludeTaskHistoryInEnhance,
includeCurrentTime,
setIncludeCurrentTime,
includeCurrentCost,
setIncludeCurrentCost,
}

return <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>
Expand Down
8 changes: 8 additions & 0 deletions webview-ui/src/i18n/locales/ca/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions webview-ui/src/i18n/locales/de/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions webview-ui/src/i18n/locales/en/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,14 @@
"profileDescription": "Custom threshold for this profile only (overrides global default)",
"inheritDescription": "This profile inherits the global default threshold ({{threshold}}%)",
"usesGlobal": "(uses global {{threshold}}%)"
},
"includeCurrentTime": {
"label": "Include current time in context",
"description": "When enabled, the current time and timezone information will be included in the system prompt. Disable this if models are stopping work due to time concerns."
},
"includeCurrentCost": {
"label": "Include current cost in context",
"description": "When enabled, the current API usage cost will be included in the system prompt. Disable this if models are stopping work due to cost concerns."
}
},
"terminal": {
Expand Down
8 changes: 8 additions & 0 deletions webview-ui/src/i18n/locales/es/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions webview-ui/src/i18n/locales/fr/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions webview-ui/src/i18n/locales/hi/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions webview-ui/src/i18n/locales/id/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions webview-ui/src/i18n/locales/it/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading