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
3 changes: 1 addition & 2 deletions apps/cockpit/instrumentation-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import { shouldCaptureAnalytics } from './src/lib/analytics/properties';
const token = process.env.NEXT_PUBLIC_COCKPIT_POSTHOG_TOKEN;
const captureLocal = process.env.NEXT_PUBLIC_COCKPIT_CAPTURE_LOCAL === 'true';
const host = typeof window === 'undefined' ? undefined : window.location.host;
const doNotTrack = typeof navigator !== 'undefined' && navigator.doNotTrack === '1';

if (shouldCaptureAnalytics({ token, captureLocal, host, doNotTrack })) {
if (shouldCaptureAnalytics({ token, captureLocal, host })) {
posthog.init(token!, {
api_host: process.env.NEXT_PUBLIC_COCKPIT_POSTHOG_HOST ?? 'https://us.i.posthog.com',
persistence: 'memory',
Expand Down
28 changes: 14 additions & 14 deletions apps/cockpit/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-langgraph-streaming-angular:serve:cockpit --port 4300",
"npx nx run cockpit-langgraph-streaming-angular:serve:cockpit --port 4300",
"cd cockpit/langgraph/streaming/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -68,7 +68,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-langgraph-persistence-angular:serve:cockpit --port 4301",
"npx nx run cockpit-langgraph-persistence-angular:serve:cockpit --port 4301",
"cd cockpit/langgraph/persistence/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -79,7 +79,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-langgraph-interrupts-angular:serve:cockpit --port 4302",
"npx nx run cockpit-langgraph-interrupts-angular:serve:cockpit --port 4302",
"cd cockpit/langgraph/interrupts/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -90,7 +90,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-langgraph-memory-angular:serve:cockpit --port 4303",
"npx nx run cockpit-langgraph-memory-angular:serve:cockpit --port 4303",
"cd cockpit/langgraph/memory/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -101,7 +101,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-langgraph-durable-execution-angular:serve:cockpit --port 4304",
"npx nx run cockpit-langgraph-durable-execution-angular:serve:cockpit --port 4304",
"cd cockpit/langgraph/durable-execution/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -112,7 +112,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-langgraph-subgraphs-angular:serve:cockpit --port 4305",
"npx nx run cockpit-langgraph-subgraphs-angular:serve:cockpit --port 4305",
"cd cockpit/langgraph/subgraphs/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -123,7 +123,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-langgraph-time-travel-angular:serve:cockpit --port 4306",
"npx nx run cockpit-langgraph-time-travel-angular:serve:cockpit --port 4306",
"cd cockpit/langgraph/time-travel/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -134,7 +134,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-langgraph-deployment-runtime-angular:serve:cockpit --port 4307",
"npx nx run cockpit-langgraph-deployment-runtime-angular:serve:cockpit --port 4307",
"cd cockpit/langgraph/deployment-runtime/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -145,7 +145,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-deep-agents-planning-angular:serve:cockpit --port 4310",
"npx nx run cockpit-deep-agents-planning-angular:serve:cockpit --port 4310",
"cd cockpit/deep-agents/planning/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -156,7 +156,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-deep-agents-filesystem-angular:serve:cockpit --port 4311",
"npx nx run cockpit-deep-agents-filesystem-angular:serve:cockpit --port 4311",
"cd cockpit/deep-agents/filesystem/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -167,7 +167,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-deep-agents-subagents-angular:serve:cockpit --port 4312",
"npx nx run cockpit-deep-agents-subagents-angular:serve:cockpit --port 4312",
"cd cockpit/deep-agents/subagents/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -178,7 +178,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-deep-agents-memory-angular:serve:cockpit --port 4313",
"npx nx run cockpit-deep-agents-memory-angular:serve:cockpit --port 4313",
"cd cockpit/deep-agents/memory/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -189,7 +189,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-deep-agents-skills-angular:serve:cockpit --port 4314",
"npx nx run cockpit-deep-agents-skills-angular:serve:cockpit --port 4314",
"cd cockpit/deep-agents/skills/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand All @@ -200,7 +200,7 @@
"options": {
"commands": [
"npx nx serve cockpit --port 4201",
"npx nx serve cockpit-deep-agents-sandboxes-angular:serve:cockpit --port 4315",
"npx nx run cockpit-deep-agents-sandboxes-angular:serve:cockpit --port 4315",
"cd cockpit/deep-agents/sandboxes/python && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123"
],
"parallel": true
Expand Down
4 changes: 2 additions & 2 deletions apps/cockpit/scripts/serve-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ process.on('SIGTERM', cleanup);
run('cockpit', 'npx nx serve cockpit --port 4201', '36');

if (allMode) {
capabilities.forEach((c) => run(c.id, `npx nx serve ${c.angularProject}:serve:cockpit --port ${c.port}`, '33'));
capabilities.forEach((c) => run(c.id, `npx nx run ${c.angularProject}:serve:cockpit --port ${c.port}`, '33'));
console.log('\n🚀 Starting cockpit + all 14 examples\n');
} else {
const cap = findCapability(capabilityArg!);
if (!cap) { console.error(`Unknown: ${capabilityArg}`); process.exit(1); }
run(cap.id, `npx nx serve ${cap.angularProject}:serve:cockpit --port ${cap.port}`, '33');
run(cap.id, `npx nx run ${cap.angularProject}:serve:cockpit --port ${cap.port}`, '33');
run(`${cap.id}-py`, `cd ${cap.pythonDir} && source $HOME/.local/bin/env 2>/dev/null; uv sync && uv run langgraph dev --port 8123`, '35');
console.log(`\n🚀 ${cap.id}: cockpit=4201 angular=${cap.port} langgraph=8123\n`);
}
2 changes: 2 additions & 0 deletions apps/cockpit/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ReactNode } from 'react';
import { cookies } from 'next/headers';
import { cssVars, ThemeProvider } from '@ngaf/ui-react';
import type { Theme } from '@ngaf/design-tokens';
import { AnalyticsBootstrap } from '../components/analytics-bootstrap';
import './cockpit.css';

export const metadata = {
Expand Down Expand Up @@ -38,6 +39,7 @@ export default async function RootLayout({ children }: RootLayoutProps) {
color: 'var(--ds-text-primary)',
}}
>
<AnalyticsBootstrap />
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</body>
</html>
Expand Down
37 changes: 37 additions & 0 deletions apps/cockpit/src/components/analytics-bootstrap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
'use client';

import { useEffect } from 'react';
import posthog from 'posthog-js';
import { getCockpitSessionId } from '../lib/analytics/distinct-id';
import { shouldCaptureAnalytics } from '../lib/analytics/properties';

/**
* Client-side analytics bootstrap. Initializes posthog-js once per
* client process when env + privacy gates pass.
*
* Mounted from the root layout. Renders nothing. Idempotent — re-renders
* (e.g. fast-refresh) check `__loaded` before re-initializing.
*/
export function AnalyticsBootstrap(): null {
useEffect(() => {
if ((posthog as unknown as { __loaded?: boolean }).__loaded) {
return;
}
const token = process.env.NEXT_PUBLIC_COCKPIT_POSTHOG_TOKEN;
const captureLocal = process.env.NEXT_PUBLIC_COCKPIT_CAPTURE_LOCAL === 'true';
const host = typeof window === 'undefined' ? undefined : window.location.host;
if (!shouldCaptureAnalytics({ token, captureLocal, host })) {
return;
}
posthog.init(token as string, {
api_host: process.env.NEXT_PUBLIC_COCKPIT_POSTHOG_HOST ?? 'https://us.i.posthog.com',
persistence: 'memory',
bootstrap: { distinctID: getCockpitSessionId() },
autocapture: false,
capture_pageview: false,
defaults: '2026-01-30',
});
}, []);
return null;
}
20 changes: 18 additions & 2 deletions apps/cockpit/src/components/run-mode/run-mode.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: MIT
import React from 'react';
'use client';

import React, { useEffect, useState } from 'react';
import { ThemedFrame } from '@ngaf/ui-react';
import { getCockpitSessionId } from '../../lib/analytics/distinct-id';

Expand All @@ -21,6 +23,20 @@ function buildIframeSrc(runtimeUrl: string, capabilitySlug: string): string {
}

export function RunMode({ entryTitle, runtimeUrl, capabilitySlug }: RunModeProps) {
// SSR-safe: render an empty iframe placeholder so HTML matches across server
// and client, then fill the src in via effect once the session id is available.
// `getCockpitSessionId()` returns a fresh UUID per process; on SSR that UUID
// would differ from the one generated client-side, breaking hydration.
const [src, setSrc] = useState<string | null>(null);

useEffect(() => {
if (runtimeUrl) {
setSrc(buildIframeSrc(runtimeUrl, capabilitySlug));
} else {
setSrc(null);
}
}, [runtimeUrl, capabilitySlug]);

if (!runtimeUrl) {
return (
<section aria-label="Run mode" className="grid place-items-center h-full text-[var(--ds-text-muted)] text-sm">
Expand All @@ -32,7 +48,7 @@ export function RunMode({ entryTitle, runtimeUrl, capabilitySlug }: RunModeProps
return (
<section aria-label="Run mode" className="h-full">
<ThemedFrame
src={buildIframeSrc(runtimeUrl, capabilitySlug)}
src={src ?? 'about:blank'}
title={`${entryTitle} live example`}
allow="clipboard-write"
className="w-full h-full border-0 rounded"
Expand Down
15 changes: 0 additions & 15 deletions apps/cockpit/src/lib/analytics/properties.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,6 @@ describe('shouldCaptureAnalytics', () => {
token: undefined,
captureLocal: true,
host: 'cockpit.example.com',
doNotTrack: false,
}),
).toBe(false);
});

test('returns false when DO_NOT_TRACK', () => {
expect(
shouldCaptureAnalytics({
token: 'phc_x',
captureLocal: true,
host: 'cockpit.example.com',
doNotTrack: true,
}),
).toBe(false);
});
Expand All @@ -31,7 +19,6 @@ describe('shouldCaptureAnalytics', () => {
token: 'phc_x',
captureLocal: false,
host: 'localhost:4201',
doNotTrack: false,
}),
).toBe(false);
});
Expand All @@ -42,7 +29,6 @@ describe('shouldCaptureAnalytics', () => {
token: 'phc_x',
captureLocal: true,
host: 'localhost:4201',
doNotTrack: false,
}),
).toBe(true);
});
Expand All @@ -53,7 +39,6 @@ describe('shouldCaptureAnalytics', () => {
token: 'phc_x',
captureLocal: false,
host: 'cockpit.example.com',
doNotTrack: false,
}),
).toBe(true);
});
Expand Down
2 changes: 0 additions & 2 deletions apps/cockpit/src/lib/analytics/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ export interface CaptureGuardInput {
token: string | undefined;
captureLocal: boolean;
host: string | undefined;
doNotTrack: boolean;
}

export function shouldCaptureAnalytics(input: CaptureGuardInput): boolean {
if (!input.token) return false;
if (input.doNotTrack) return false;
if (!input.captureLocal && isLocalhost(input.host)) return false;
return true;
}
Expand Down
28 changes: 22 additions & 6 deletions cockpit/ag-ui/streaming/angular/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,33 @@
"targets": {
"build": {
"executor": "@angular/build:application",
"outputs": ["{options.outputPath.base}"],
"outputs": [
"{options.outputPath.base}"
],
"options": {
"outputPath": {
"base": "dist/cockpit/ag-ui/streaming/angular",
"browser": ""
},
"browser": "cockpit/ag-ui/streaming/angular/src/main.ts",
"tsConfig": "cockpit/ag-ui/streaming/angular/tsconfig.app.json",
"styles": ["cockpit/ag-ui/streaming/angular/src/styles.css"]
"styles": [
"cockpit/ag-ui/streaming/angular/src/styles.css"
]
},
"configurations": {
"production": {
"budgets": [
{ "type": "initial", "maximumWarning": "500kb", "maximumError": "1mb" },
{ "type": "anyComponentStyle", "maximumWarning": "4kb", "maximumError": "8kb" }
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "4kb",
"maximumError": "8kb"
}
],
"outputHashing": "none"
},
Expand All @@ -42,8 +54,12 @@
"continuous": true,
"executor": "@angular/build:dev-server",
"configurations": {
"production": { "buildTarget": "cockpit-ag-ui-streaming-angular:build:production" },
"development": { "buildTarget": "cockpit-ag-ui-streaming-angular:build:development" }
"production": {
"buildTarget": "cockpit-ag-ui-streaming-angular:build:production"
},
"development": {
"buildTarget": "cockpit-ag-ui-streaming-angular:build:development"
}
},
"defaultConfiguration": "development",
"options": {
Expand Down
Loading
Loading