mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
[codex] Derive object relay URL from telemetry relay (#4036)
* Derive object relay URL from telemetry relay * Normalize telemetry relay URL before object derivation Generated-By: looper 0.9.7 (runner=fixer, agent=codex)
This commit is contained in:
@@ -177,7 +177,10 @@ function mergeTraceSafeManifests(
|
||||
|
||||
function inferObjectRegistrationRelayUrl(env: NodeJS.ProcessEnv = process.env): string | null {
|
||||
const objectRelayUrl = env.OPEN_DESIGN_OBJECT_RELAY_URL?.trim();
|
||||
if (!objectRelayUrl) return null;
|
||||
if (!objectRelayUrl) {
|
||||
const telemetryRelayUrl = env.OPEN_DESIGN_TELEMETRY_RELAY_URL?.trim();
|
||||
return telemetryRelayUrl ? telemetryRelayUrl.replace(/\/+$/, '') : null;
|
||||
}
|
||||
try {
|
||||
const url = new URL(objectRelayUrl);
|
||||
url.pathname = url.pathname.replace(/\/api\/objects\/batch\/?$/, '/api/langfuse');
|
||||
|
||||
@@ -137,6 +137,18 @@ function storageRef(projectId: string, runId: string, objectClass: ObjectClass,
|
||||
function inferRelayUrl(env: NodeJS.ProcessEnv): string | null {
|
||||
const explicit = env.OPEN_DESIGN_OBJECT_RELAY_URL?.trim();
|
||||
if (explicit) return explicit.replace(/\/+$/, '');
|
||||
const rawTelemetryRelayUrl = env.OPEN_DESIGN_TELEMETRY_RELAY_URL?.trim();
|
||||
if (!rawTelemetryRelayUrl) return null;
|
||||
const telemetryRelayUrl = rawTelemetryRelayUrl.replace(/\/+$/, '');
|
||||
try {
|
||||
const url = new URL(telemetryRelayUrl);
|
||||
if (!/\/api\/langfuse\/?$/u.test(url.pathname)) return null;
|
||||
url.pathname = url.pathname.replace(/\/api\/langfuse\/?$/u, '/api/objects/batch');
|
||||
return url.toString().replace(/\/+$/, '');
|
||||
} catch {
|
||||
const derived = telemetryRelayUrl.replace(/\/api\/langfuse\/?$/u, '/api/objects/batch');
|
||||
return derived === telemetryRelayUrl ? null : derived.replace(/\/+$/, '');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -440,7 +440,7 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps production telemetry relay object uploads disabled while preserving fallback manifests', async () => {
|
||||
it('derives production object uploads from the telemetry relay while keeping bodies out of Langfuse', async () => {
|
||||
await writeAppCfg({
|
||||
installationId: 'install-uuid-1',
|
||||
telemetry: { metrics: true, content: true, artifactManifest: true },
|
||||
@@ -449,9 +449,35 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
|
||||
await mkdir(projectDir, { recursive: true });
|
||||
await writeFile(path.join(projectDir, 'brief.txt'), 'private attachment body');
|
||||
await writeFile(path.join(projectDir, 'index.html'), '<!doctype html><h1>private artifact</h1>');
|
||||
const fetchSpy = vi
|
||||
.fn()
|
||||
.mockResolvedValue(new Response('{}', { status: 207 }));
|
||||
const fetchSpy = vi.fn(async (url: string, init: RequestInit) => {
|
||||
if (url.includes('/api/objects/authorize')) {
|
||||
const parsed = JSON.parse(init.body as string) as {
|
||||
objects: Array<{ storage_ref: string; sha256: string; size_bytes: number }>;
|
||||
};
|
||||
expect(parsed.objects).toHaveLength(2);
|
||||
return new Response(JSON.stringify({ upload_token: 'upload-token' }), { status: 200 });
|
||||
}
|
||||
if (url.includes('/api/objects/batch')) {
|
||||
const parsed = JSON.parse(init.body as string) as {
|
||||
upload_token: string;
|
||||
objects: Array<{ storage_ref: string; content_base64: string }>;
|
||||
};
|
||||
expect(parsed.upload_token).toBe('upload-token');
|
||||
expect(parsed.objects).toHaveLength(2);
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
objects: parsed.objects.map((object) => ({
|
||||
storage_ref: object.storage_ref,
|
||||
status: 'available',
|
||||
size_bytes: Buffer.from(object.content_base64, 'base64').byteLength,
|
||||
sha256: `sha256:${object.storage_ref.split('/').at(-1)}`,
|
||||
})),
|
||||
}),
|
||||
{ status: 200 },
|
||||
);
|
||||
}
|
||||
return new Response('{}', { status: 207 });
|
||||
});
|
||||
const priorNodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
process.env.OPEN_DESIGN_TELEMETRY_RELAY_URL = 'https://telemetry.open-design.ai/api/langfuse';
|
||||
@@ -499,10 +525,12 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
|
||||
delete process.env.LANGFUSE_SECRET_KEY;
|
||||
}
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(4);
|
||||
expect(fetchSpy.mock.calls[0]![0]).toContain('/api/langfuse');
|
||||
expect(fetchSpy.mock.calls[0]![0]).not.toContain('/api/objects/');
|
||||
const init = fetchSpy.mock.calls[0]![1] as RequestInit;
|
||||
expect(fetchSpy.mock.calls[1]![0]).toBe('https://telemetry.open-design.ai/api/objects/authorize');
|
||||
expect(fetchSpy.mock.calls[2]![0]).toBe('https://telemetry.open-design.ai/api/objects/batch');
|
||||
expect(fetchSpy.mock.calls[3]![0]).toContain('/api/langfuse');
|
||||
const init = fetchSpy.mock.calls[3]![1] as RequestInit;
|
||||
const langfuseBody = init.body as string;
|
||||
expect(langfuseBody).not.toContain('private attachment body');
|
||||
expect(langfuseBody).not.toContain('<!doctype html><h1>private artifact</h1>');
|
||||
@@ -519,7 +547,7 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
|
||||
object_class: 'artifact',
|
||||
status: 'ok',
|
||||
stored_in_open_design: true,
|
||||
size_bytes: 41,
|
||||
size_bytes: '<!doctype html><h1>private artifact</h1>'.length,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -577,7 +605,6 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
|
||||
return new Response('{}', { status: 207 });
|
||||
});
|
||||
|
||||
process.env.OPEN_DESIGN_OBJECT_RELAY_URL = 'https://telemetry.open-design.ai/api/objects/batch';
|
||||
process.env.OPEN_DESIGN_TELEMETRY_RELAY_URL = 'https://telemetry.open-design.ai/api/langfuse';
|
||||
process.env.LANGFUSE_PUBLIC_KEY = 'pk';
|
||||
process.env.LANGFUSE_SECRET_KEY = 'sk';
|
||||
@@ -613,7 +640,6 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
|
||||
fetchImpl: fetchSpy as any,
|
||||
});
|
||||
} finally {
|
||||
delete process.env.OPEN_DESIGN_OBJECT_RELAY_URL;
|
||||
delete process.env.OPEN_DESIGN_TELEMETRY_RELAY_URL;
|
||||
delete process.env.LANGFUSE_PUBLIC_KEY;
|
||||
delete process.env.LANGFUSE_SECRET_KEY;
|
||||
|
||||
@@ -272,12 +272,33 @@ describe('buildTraceObjectManifests', () => {
|
||||
expect(manifests?.artifactManifest).toHaveLength(101);
|
||||
});
|
||||
|
||||
it('leaves production telemetry relay configuration to fallback manifests without reading project files', async () => {
|
||||
it('derives the object relay endpoint from the telemetry relay endpoint', async () => {
|
||||
const projectsRoot = path.join(dataDir, 'projects');
|
||||
const projectDir = path.join(projectsRoot, 'proj-1');
|
||||
await mkdir(projectDir, { recursive: true });
|
||||
await writeFile(path.join(projectDir, 'artifact.txt'), 'release artifact');
|
||||
const fetchSpy = vi.fn();
|
||||
const fetchSpy = vi.fn(async (url: string, init: RequestInit) => {
|
||||
const parsed = JSON.parse(init.body as string) as {
|
||||
objects: Array<{ storage_ref: string; content_base64?: string }>;
|
||||
};
|
||||
if (url.includes('/api/objects/authorize')) {
|
||||
expect(parsed.objects).toHaveLength(1);
|
||||
return new Response(JSON.stringify({ upload_token: 'upload-token' }), { status: 200 });
|
||||
}
|
||||
expect(url).toBe('https://telemetry.open-design.ai/api/objects/batch');
|
||||
expect((parsed as unknown as { upload_token: string }).upload_token).toBe('upload-token');
|
||||
expect(parsed.objects).toHaveLength(1);
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
objects: parsed.objects.map((object) => ({
|
||||
storage_ref: object.storage_ref,
|
||||
status: 'available',
|
||||
size_bytes: Buffer.from(object.content_base64!, 'base64').byteLength,
|
||||
})),
|
||||
}),
|
||||
{ status: 200 },
|
||||
);
|
||||
});
|
||||
|
||||
const manifests = await buildTraceObjectManifests({
|
||||
installationId: 'install-1',
|
||||
@@ -292,14 +313,21 @@ describe('buildTraceObjectManifests', () => {
|
||||
fetchImpl: fetchSpy as any,
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
OPEN_DESIGN_TELEMETRY_RELAY_URL: 'https://telemetry.open-design.ai/api/langfuse',
|
||||
OPEN_DESIGN_TELEMETRY_RELAY_URL: 'https://telemetry.open-design.ai/api/langfuse//',
|
||||
},
|
||||
now: () => new Date('2026-06-08T00:00:00.000Z'),
|
||||
});
|
||||
|
||||
expect(manifests).toBeUndefined();
|
||||
expect(projectFileReadTracker.calls).toBe(0);
|
||||
expect(fetchSpy).not.toHaveBeenCalled();
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(2);
|
||||
expect(fetchSpy.mock.calls[0]![0]).toBe('https://telemetry.open-design.ai/api/objects/authorize');
|
||||
expect(fetchSpy.mock.calls[1]![0]).toBe('https://telemetry.open-design.ai/api/objects/batch');
|
||||
expect(projectFileReadTracker.calls).toBe(1);
|
||||
expect(manifests?.completeness).toBe('complete');
|
||||
expect(manifests?.artifactManifest?.[0]).toMatchObject({
|
||||
status: 'ok',
|
||||
stored_in_open_design: true,
|
||||
size_bytes: 'release artifact'.length,
|
||||
});
|
||||
});
|
||||
|
||||
it('skips over-limit project files before loading their contents', async () => {
|
||||
|
||||
Reference in New Issue
Block a user