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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable changes to Brain are documented in this file.

## [Unreleased]

### Changed

- Rename the Langfuse endpoint environment variable to `LANGFUSE_BASE_URL`
for Chat Assistant tracing and newly created GitHub Deploy Devboxes.
Deployments must rename `LANGFUSE_HOST`; the old name is no longer read or
forwarded. Recreate existing Devboxes to apply the updated environment.

## [2.0.14] - 2026-09-10

### Added
Expand Down
4 changes: 2 additions & 2 deletions apps/ui/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ GITHUB_DEPLOY_MODEL=
# of SYSTEM_OPENAI_* and host CODEX_GATEWAY_OPENAI_* values.
GITHUB_DEPLOY_OPENAI_API_KEY=
GITHUB_DEPLOY_OPENAI_BASE_URL=
# Optional Chat Assistant telemetry. Set both keys and LANGFUSE_HOST to enable.
# Optional Chat Assistant telemetry. Set both keys and LANGFUSE_BASE_URL to enable.
# Also forwarded into newly created GitHub Deploy Devboxes for Codex traces.
LANGFUSE_PUBLIC_KEY=
LANGFUSE_SECRET_KEY=
# Langfuse instance root URL. Blank disables telemetry; no Cloud fallback.
# Self-hosted Langfuse is supported. Do not append /api/public/otel.
LANGFUSE_HOST=
LANGFUSE_BASE_URL=

GITHUB_APP_ID=
GITHUB_APP_PRIVATE_KEY=
Expand Down
27 changes: 23 additions & 4 deletions apps/ui/src/features/deploy/task/runner.github-ai-proxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const ENV_KEYS = [
"GITHUB_DEPLOY_MODEL",
"GITHUB_DEPLOY_OPENAI_API_KEY",
"GITHUB_DEPLOY_OPENAI_BASE_URL",
"LANGFUSE_HOST",
"LANGFUSE_BASE_URL",
"LANGFUSE_PUBLIC_KEY",
"LANGFUSE_SECRET_KEY",
"SYSTEM_OPENAI_API_KEY",
Expand Down Expand Up @@ -244,7 +244,7 @@ describe("deployment AI Proxy credentials", () => {
"https://brain.test/api/deploy-agent/mcp/v1";
delete process.env.GITHUB_DEPLOY_OPENAI_API_KEY;
delete process.env.GITHUB_DEPLOY_OPENAI_BASE_URL;
delete process.env.LANGFUSE_HOST;
delete process.env.LANGFUSE_BASE_URL;
delete process.env.LANGFUSE_PUBLIC_KEY;
delete process.env.LANGFUSE_SECRET_KEY;
});
Expand Down Expand Up @@ -386,17 +386,36 @@ describe("deployment AI Proxy credentials", () => {
it("forwards trimmed LANGFUSE_* values when they are set", () => {
process.env.LANGFUSE_PUBLIC_KEY = " pk-lf-test ";
process.env.LANGFUSE_SECRET_KEY = " sk-lf-test ";
process.env.LANGFUSE_HOST = " https://langfuse.example.com ";
process.env.LANGFUSE_BASE_URL = " https://langfuse.example.com ";
expect(buildCodexGatewayEnv(RESOLVED_GATEWAY_CREDENTIALS)).toEqual({
CODEX_GATEWAY_MODEL: "deploy-model",
CODEX_GATEWAY_OPENAI_API_KEY: "resolved-key",
CODEX_GATEWAY_OPENAI_BASE_URL: "https://resolved.example/v1",
LANGFUSE_PUBLIC_KEY: "pk-lf-test",
LANGFUSE_SECRET_KEY: "sk-lf-test",
LANGFUSE_HOST: "https://langfuse.example.com",
LANGFUSE_BASE_URL: "https://langfuse.example.com",
});
});

it("does not forward the removed Langfuse host variable", () => {
/* eslint-disable turbo/no-undeclared-env-vars -- Regression test intentionally sets the removed variable, which must stay out of turbo.json. */
const previous = process.env.LANGFUSE_HOST;
try {
process.env.LANGFUSE_HOST = "https://old-langfuse.example.com";
delete process.env.LANGFUSE_BASE_URL;
const env = buildCodexGatewayEnv(RESOLVED_GATEWAY_CREDENTIALS);
expect(env.LANGFUSE_HOST).toBeUndefined();
expect(env.LANGFUSE_BASE_URL).toBeUndefined();
} finally {
if (previous === undefined) {
delete process.env.LANGFUSE_HOST;
} else {
process.env.LANGFUSE_HOST = previous;
}
}
/* eslint-enable turbo/no-undeclared-env-vars */
});

it("uses GITHUB_DEPLOY_OPENAI_* when both are set", () => {
process.env.GITHUB_DEPLOY_OPENAI_API_KEY = " github-override-key ";
process.env.GITHUB_DEPLOY_OPENAI_BASE_URL = " https://override.example/v1 ";
Expand Down
6 changes: 3 additions & 3 deletions apps/ui/src/features/deploy/task/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1116,15 +1116,15 @@ export function buildCodexGatewayEnv(

const langfusePublicKey = compactEnvValue(process.env.LANGFUSE_PUBLIC_KEY);
const langfuseSecretKey = compactEnvValue(process.env.LANGFUSE_SECRET_KEY);
const langfuseHost = compactEnvValue(process.env.LANGFUSE_HOST);
const langfuseBaseUrl = compactEnvValue(process.env.LANGFUSE_BASE_URL);
if (langfusePublicKey != null) {
env.LANGFUSE_PUBLIC_KEY = langfusePublicKey;
}
if (langfuseSecretKey != null) {
env.LANGFUSE_SECRET_KEY = langfuseSecretKey;
}
if (langfuseHost != null) {
env.LANGFUSE_HOST = langfuseHost;
if (langfuseBaseUrl != null) {
env.LANGFUSE_BASE_URL = langfuseBaseUrl;
}

return env;
Expand Down
19 changes: 15 additions & 4 deletions apps/ui/src/lib/observability/langfuse-core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,23 @@ test("disables Langfuse when credentials are absent or incomplete", () => {
);
});

test("does not accept the removed host environment variable", () => {
assert.equal(
getLangfuseConfigFromEnv({
LANGFUSE_PUBLIC_KEY: "pk-lf-test",
LANGFUSE_SECRET_KEY: "sk-lf-test",
LANGFUSE_HOST: "https://langfuse.example.test",
}),
null
);
});

test("trims credentials and requires an explicit host", () => {
assert.deepEqual(
getLangfuseConfigFromEnv({
LANGFUSE_PUBLIC_KEY: " pk-lf-test ",
LANGFUSE_SECRET_KEY: " sk-lf-test ",
LANGFUSE_HOST: " https://langfuse.example.test/// ",
LANGFUSE_BASE_URL: " https://langfuse.example.test/// ",
}),
{
publicKey: "pk-lf-test",
Expand All @@ -32,7 +43,7 @@ test("trims credentials and requires an explicit host", () => {
getLangfuseConfigFromEnv({
LANGFUSE_PUBLIC_KEY: "pk-lf-test",
LANGFUSE_SECRET_KEY: "sk-lf-test",
LANGFUSE_HOST: " ",
LANGFUSE_BASE_URL: " ",
}),
null
);
Expand All @@ -43,7 +54,7 @@ for (const host of [undefined, "", " "]) {
const env = {
LANGFUSE_PUBLIC_KEY: "pk-test",
LANGFUSE_SECRET_KEY: "sk-test",
LANGFUSE_HOST: host,
LANGFUSE_BASE_URL: host,
};
assert.equal(getLangfuseConfigFromEnv(env), null);
});
Expand All @@ -54,7 +65,7 @@ test("allows explicitly configured Langfuse Cloud", () => {
getLangfuseConfigFromEnv({
LANGFUSE_PUBLIC_KEY: "pk-test",
LANGFUSE_SECRET_KEY: "sk-test",
LANGFUSE_HOST: "https://cloud.langfuse.com",
LANGFUSE_BASE_URL: "https://cloud.langfuse.com",
})?.baseUrl,
"https://cloud.langfuse.com"
);
Expand Down
3 changes: 2 additions & 1 deletion apps/ui/src/lib/observability/langfuse-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export function getLangfuseConfigFromEnv(
const publicKey = env.LANGFUSE_PUBLIC_KEY?.trim() ?? "";
const secretKey = env.LANGFUSE_SECRET_KEY?.trim() ?? "";

const baseUrl = env.LANGFUSE_HOST?.trim().replace(TRAILING_SLASHES, "") ?? "";
const baseUrl =
env.LANGFUSE_BASE_URL?.trim().replace(TRAILING_SLASHES, "") ?? "";

if (publicKey === "" || secretKey === "" || baseUrl === "") {
return null;
Expand Down
4 changes: 2 additions & 2 deletions apps/ui/src/lib/observability/langfuse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ const {

test("failed integration registration disables telemetry and shuts down the SDK", async () => {
const previous = {
LANGFUSE_HOST: process.env.LANGFUSE_HOST,
LANGFUSE_BASE_URL: process.env.LANGFUSE_BASE_URL,
LANGFUSE_PUBLIC_KEY: process.env.LANGFUSE_PUBLIC_KEY,
LANGFUSE_SECRET_KEY: process.env.LANGFUSE_SECRET_KEY,
};
try {
Object.assign(process.env, {
LANGFUSE_HOST: "https://langfuse.example.test",
LANGFUSE_BASE_URL: "https://langfuse.example.test",
LANGFUSE_PUBLIC_KEY: "pk-test",
LANGFUSE_SECRET_KEY: "sk-test",
});
Expand Down
2 changes: 1 addition & 1 deletion charts/brain-system/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ then edit `$private_values_file`, especially:
- `GITHUB_USER_TOKEN_ENCRYPTION_KEY`: keep stable; changing it prevents decrypting previously stored GitHub user tokens
- Assistant chat values: `SYSTEM_OPENAI_*` funds `FREE_CHAT_TURNS` successful turns for eligible Active Free Trial workspaces; later turns use the caller's AI Proxy (`AI_PROXY_TOKEN_NAME`). `ASSISTANT_GATEWAY_MODEL` optionally selects the Chat Agent model
- optional GitHub Deploy model (`GITHUB_DEPLOY_MODEL`); blank uses `gpt-5.5`. Independent of `ASSISTANT_GATEWAY_MODEL`, which selects the Chat Agent model
- optional Chat Assistant Langfuse tracing (`LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, `LANGFUSE_HOST`); all three values must be set. An empty host disables tracing; Cloud requires an explicit `https://cloud.langfuse.com` or `https://us.cloud.langfuse.com`. Use an instance root URL without `/api/public/otel`. These credentials enable Chat tracing in Brain UI and are forwarded into newly created GitHub Deploy Devboxes for Codex traces. Existing Devboxes retain their old environment until recreated.
- optional Chat Assistant Langfuse tracing (`LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, `LANGFUSE_BASE_URL`); all three values must be set. An empty host disables tracing; Cloud requires an explicit `https://cloud.langfuse.com` or `https://us.cloud.langfuse.com`. Use an instance root URL without `/api/public/otel`. These credentials enable Chat tracing in Brain UI and are forwarded into newly created GitHub Deploy Devboxes for Codex traces. Existing Devboxes retain their old environment until recreated.
- optional platform-funded GitHub Deploy connection (`GITHUB_DEPLOY_OPENAI_API_KEY`, `GITHUB_DEPLOY_OPENAI_BASE_URL`); when both are set, GitHub Deploy uses them. When both are blank, it uses the caller's AI Proxy. A partial pair is an error; it never reuses Chat Agent or host Codex credentials
- `MARKETING_EVENTS_INGEST_SECRET`: shared bearer secret for trusted lifecycle event producers
- `MARKETING_CONSENT_SIGNING_KEY`: shared HS256 secret used to verify Desktop-issued consent tokens
Expand Down
4 changes: 2 additions & 2 deletions charts/brain-system/values.local.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ ui:
SYSTEM_OPENAI_API_KEY: "REPLACE_ME_OPENAI_COMPATIBLE_KEY"
SYSTEM_OPENAI_API_BASE_URL: "https://api.openai.com/v1"
FREE_CHAT_TURNS: "5"
# Optional Chat Assistant telemetry. Set both keys and LANGFUSE_HOST to enable.
# Optional Chat Assistant telemetry. Set both keys and LANGFUSE_BASE_URL to enable.
# Also forwarded into newly created GitHub Deploy Devboxes for Codex traces.
LANGFUSE_PUBLIC_KEY: ""
LANGFUSE_SECRET_KEY: ""
# Langfuse instance root URL. Blank disables telemetry; no Cloud fallback.
# Self-hosted Langfuse is supported. Do not append /api/public/otel.
LANGFUSE_HOST: ""
LANGFUSE_BASE_URL: ""
# User-billed turns use the Sealos AI proxy.
# Later Chat Agent turns use the caller's Sealos AI Proxy.
AI_PROXY_TOKEN_NAME: "sealos-brain"
Expand Down
4 changes: 2 additions & 2 deletions charts/brain-system/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ ui:
# of SYSTEM_OPENAI_* and host CODEX_GATEWAY_OPENAI_* values.
GITHUB_DEPLOY_OPENAI_API_KEY: ""
GITHUB_DEPLOY_OPENAI_BASE_URL: ""
# Optional Chat Assistant telemetry. Set both keys and LANGFUSE_HOST to enable.
# Optional Chat Assistant telemetry. Set both keys and LANGFUSE_BASE_URL to enable.
# Also forwarded into newly created GitHub Deploy Devboxes for Codex traces.
LANGFUSE_PUBLIC_KEY: ""
LANGFUSE_SECRET_KEY: ""
# Langfuse instance root URL. Blank disables telemetry; no Cloud fallback.
# Self-hosted Langfuse is supported. Do not append /api/public/otel.
LANGFUSE_HOST: ""
LANGFUSE_BASE_URL: ""
GITHUB_OAUTH_CLIENT_ID: ""
GITHUB_OAUTH_CLIENT_SECRET: ""
GITHUB_USER_TOKEN_ENCRYPTION_KEY: ""
Expand Down
2 changes: 1 addition & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"KUBERNETES_SERVICE_HOST",
"KUBERNETES_SERVICE_PORT",
"KUBECONFIG",
"LANGFUSE_HOST",
"LANGFUSE_BASE_URL",
"LANGFUSE_PUBLIC_KEY",
"LANGFUSE_SECRET_KEY",
"MARKETING_CONSENT_SIGNING_KEY",
Expand Down
Loading