Compare commits

...

4 Commits

Author SHA1 Message Date
Elephant Lumps 388aec10b5 move init outside function to keep from potentially re-running 2025-05-02 00:24:10 -05:00
Elephant Lumps f97415eabe add feature flags constant 2025-05-02 00:15:58 -05:00
Elephant Lumps 384707678f changeset 2025-05-01 23:32:16 -05:00
Elephant Lumps d676fb2555 added posthog remote config 2025-05-01 23:31:24 -05:00
7 changed files with 71 additions and 28 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"claude-dev": minor
---
Add remote config with posthog allowing for disabling new features until they're reading, making for a better developer experience.
+3 -2
View File
@@ -4,6 +4,7 @@ import { version as extensionVersion } from "../../../package.json"
import type { TaskFeedbackType } from "@shared/WebviewMessage"
import type { BrowserSettings } from "@shared/BrowserSettings"
import { posthogConfig } from "@/shared/services/config/posthog-config"
/**
* PostHogClient handles telemetry event tracking for the Cline extension
@@ -93,8 +94,8 @@ class PostHogClient {
* Initializes PostHog client with configuration
*/
private constructor() {
this.client = new PostHog("phc_qfOAGxZw2TL5O8p9KYd9ak3bPBFzfjC8fy5L6jNWY7K", {
host: "https://us.i.posthog.com",
this.client = new PostHog(posthogConfig.apiKey, {
host: posthogConfig.host,
enableExceptionAutocapture: false,
})
}
@@ -0,0 +1,5 @@
// Public PostHog key (safe for open source)
export const posthogConfig = {
apiKey: "phc_qfOAGxZw2TL5O8p9KYd9ak3bPBFzfjC8fy5L6jNWY7K",
host: "https://us.i.posthog.com",
}
@@ -0,0 +1,6 @@
export const FEATURE_FLAGS = {
CUSTOM_INSTRUCTIONS: "custom-instructions",
// Further flags here
} as const
export type FeatureFlag = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS]
+12 -3
View File
@@ -3,13 +3,22 @@ import type { ReactNode } from "react"
import { ExtensionStateContextProvider } from "./context/ExtensionStateContext"
import { FirebaseAuthProvider } from "./context/FirebaseAuthContext"
import { HeroUIProvider } from "@heroui/react"
import { PostHogProvider } from "posthog-js/react"
import { posthogConfig } from "@shared/services/config/posthog-config"
import posthog from "posthog-js"
posthog.init(posthogConfig.apiKey, {
api_host: posthogConfig.host,
})
export function Providers({ children }: { children: ReactNode }) {
return (
<ExtensionStateContextProvider>
<FirebaseAuthProvider>
<HeroUIProvider>{children}</HeroUIProvider>
</FirebaseAuthProvider>
<PostHogProvider client={posthog}>
<FirebaseAuthProvider>
<HeroUIProvider>{children}</HeroUIProvider>
</FirebaseAuthProvider>
</PostHogProvider>
</ExtensionStateContextProvider>
)
}
@@ -10,7 +10,8 @@ import { useEvent } from "react-use"
import { ExtensionMessage } from "@shared/ExtensionMessage"
import BrowserSettingsSection from "./BrowserSettingsSection"
import TerminalSettingsSection from "./TerminalSettingsSection"
import { useFeatureFlag } from "@/hooks/useFeatureFlag"
import { FEATURE_FLAGS } from "@shared/services/feature-flags/feature-flags"
const { IS_DEV } = process.env
type SettingsViewProps = {
@@ -82,16 +83,16 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
// validate as soon as the component is mounted
/*
useEffect will use stale values of variables if they are not included in the dependency array.
so trying to use useEffect with a dependency array of only one value for example will use any
other variables' old values. In most cases you don't want this, and should opt to use react-use
hooks.
useEffect will use stale values of variables if they are not included in the dependency array.
so trying to use useEffect with a dependency array of only one value for example will use any
other variables' old values. In most cases you don't want this, and should opt to use react-use
hooks.
// uses someVar and anotherVar
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [someVar])
// uses someVar and anotherVar
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [someVar])
If we only want to run code once on mount we can use react-use's useEffectOnce or useMount
*/
*/
const handleMessage = useCallback(
(event: MessageEvent) => {
@@ -145,6 +146,8 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
handleSubmit(true)
}
const showCustomInstructions = useFeatureFlag(FEATURE_FLAGS.CUSTOM_INSTRUCTIONS)
return (
<div className="fixed top-0 left-0 right-0 bottom-0 pt-[10px] pr-0 pb-0 pl-5 flex flex-col overflow-hidden">
<div className="flex justify-between items-center mb-[13px] pr-[17px]">
@@ -183,20 +186,24 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
/>
)}
<div className="mb-[5px]">
<VSCodeTextArea
value={customInstructions ?? ""}
className="w-full"
resize="vertical"
rows={4}
placeholder={'e.g. "Run unit tests at the end", "Use TypeScript with async/await", "Speak in Spanish"'}
onInput={(e: any) => setCustomInstructions(e.target?.value ?? "")}>
<span className="font-medium">Custom Instructions</span>
</VSCodeTextArea>
<p className="text-xs mt-[5px] text-[var(--vscode-descriptionForeground)]">
These instructions are added to the end of the system prompt sent with every request.
</p>
</div>
{showCustomInstructions && (
<div className="mb-[5px]">
<VSCodeTextArea
value={customInstructions ?? ""}
className="w-full"
resize="vertical"
rows={4}
placeholder={
'e.g. "Run unit tests at the end", "Use TypeScript with async/await", "Speak in Spanish"'
}
onInput={(e: any) => setCustomInstructions(e.target?.value ?? "")}>
<span className="font-medium">Custom Instructions</span>
</VSCodeTextArea>
<p className="text-xs mt-[5px] text-[var(--vscode-descriptionForeground)]">
These instructions are added to the end of the system prompt sent with every request.
</p>
</div>
)}
<div className="mb-[5px]">
<VSCodeCheckbox
+10
View File
@@ -0,0 +1,10 @@
import { useFeatureFlagPayload } from "posthog-js/react"
export const useFeatureFlag = (flagName: string): boolean => {
const payload = useFeatureFlagPayload(flagName) as { enabled: boolean }
if (payload && payload.enabled) {
return payload.enabled
}
console.warn(`Feature flag ${flagName} not found or missing enabled property.`)
return false
}