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
10 changes: 10 additions & 0 deletions cockpit/ag-ui/streaming/angular/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@cacheplane/cockpit-ag-ui-streaming-angular",
"version": "0.0.1",
"peerDependencies": {
"@cacheplane/ag-ui": "^0.0.1",
"@cacheplane/chat": "^0.0.1"
},
"license": "PolyForm-Noncommercial-1.0.0",
"sideEffects": false
}
61 changes: 61 additions & 0 deletions cockpit/ag-ui/streaming/angular/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "cockpit-ag-ui-streaming-angular",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "cockpit/ag-ui/streaming/angular/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@angular/build:application",
"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"]
},
"configurations": {
"production": {
"budgets": [
{ "type": "initial", "maximumWarning": "500kb", "maximumError": "1mb" },
{ "type": "anyComponentStyle", "maximumWarning": "4kb", "maximumError": "8kb" }
],
"outputHashing": "none"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true,
"fileReplacements": [
{
"replace": "cockpit/ag-ui/streaming/angular/src/environments/environment.ts",
"with": "cockpit/ag-ui/streaming/angular/src/environments/environment.development.ts"
}
]
}
},
"defaultConfiguration": "production"
},
"serve": {
"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" }
},
"defaultConfiguration": "development",
"options": {
"proxyConfig": "cockpit/ag-ui/streaming/angular/proxy.conf.json"
}
},
"smoke": {
"executor": "nx:run-commands",
"options": {
"cwd": "cockpit/ag-ui/streaming/angular",
"command": "npx tsx -e \"import { agUiStreamingAngularModule } from './src/index.ts'; const module = agUiStreamingAngularModule; if (module.id !== 'ag-ui-streaming-angular' || module.title !== 'AG-UI Streaming (Angular)') { throw new Error('Unexpected module shape for ' + module.id); }\""
}
}
}
}
7 changes: 7 additions & 0 deletions cockpit/ag-ui/streaming/angular/prompts/streaming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# AG-UI Streaming (Angular)

This capability demonstrates real-time token streaming from an AG-UI compatible agent using the `@cacheplane/chat` Angular component library. The example shows how to wire the `AG_UI_AGENT` injection token (provided by `provideAgUiAgent`) into the `<chat>` host component and compose `<chat-messages>`, `<chat-input>`, and `<chat-typing-indicator>` to deliver a responsive, streaming chat experience.

Key components used: `<chat>`, `<chat-messages>`, `<chat-input>`, `<chat-typing-indicator>`. The `provideAgUiAgent` provider handles SSE event processing from the AG-UI streaming endpoint, and the chat components subscribe reactively without any manual subscription management.

The demo illustrates the chat-runtime decoupling: the same `<chat>` composition works with any agent runtime — LangGraph, AG-UI, or others — by conforming to the `AgentRef` interface.
8 changes: 8 additions & 0 deletions cockpit/ag-ui/streaming/angular/proxy.conf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"/agent": {
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true,
"ws": true
}
}
10 changes: 10 additions & 0 deletions cockpit/ag-ui/streaming/angular/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
import { ApplicationConfig } from '@angular/core';
import { provideAgUiAgent } from '@cacheplane/ag-ui';
import { environment } from '../environments/environment';

export const appConfig: ApplicationConfig = {
providers: [
provideAgUiAgent({ url: environment.agUiUrl }),
],
};
29 changes: 29 additions & 0 deletions cockpit/ag-ui/streaming/angular/src/app/streaming.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
import { Component, inject } from '@angular/core';
import { ChatComponent } from '@cacheplane/chat';
import { AG_UI_AGENT } from '@cacheplane/ag-ui';
import { ExampleChatLayoutComponent } from '@cacheplane/example-layouts';

/**
* Streaming demo — simplest possible @cacheplane/chat integration with AG-UI.
*
* Injects the AG_UI_AGENT token (provided by provideAgUiAgent) and passes it
* to the prebuilt <chat> composition. The composition handles message rendering,
* input, typing indicator, and error display internally.
*
* Demonstrates the chat-runtime decoupling: same <chat> composition as the
* LangGraph cockpit, AG-UI runtime instead of LangGraph.
*/
@Component({
selector: 'app-streaming',
standalone: true,
imports: [ChatComponent, ExampleChatLayoutComponent],
template: `
<example-chat-layout>
<chat main [agent]="agent" class="flex-1 min-w-0" />
</example-chat-layout>
`,
})
export class StreamingComponent {
protected readonly agent = inject(AG_UI_AGENT);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Development environment configuration.
*
* Points to a local AG-UI compatible agent server started on port 3000.
* The dev-server proxy (proxy.conf.json) forwards /agent to http://localhost:3000.
*/
export const environment = {
production: false,
agUiUrl: 'http://localhost:3000/agent',
};
10 changes: 10 additions & 0 deletions cockpit/ag-ui/streaming/angular/src/environments/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Production environment configuration.
*
* Uses relative /agent URL — configure a reverse proxy or Vercel rewrite
* to forward requests to the AG-UI backend.
*/
export const environment = {
production: true,
agUiUrl: '/agent',
};
13 changes: 13 additions & 0 deletions cockpit/ag-ui/streaming/angular/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>AG-UI Streaming — Angular</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-950 text-gray-100 h-screen">
<app-streaming></app-streaming>
</body>
</html>
33 changes: 33 additions & 0 deletions cockpit/ag-ui/streaming/angular/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export interface CockpitCapabilityModule {
id: string;
manifestIdentity: {
product: 'ag-ui';
section: 'core-capabilities';
topic: 'streaming';
page: 'overview';
language: 'angular';
};
title: string;
docsPath: string;
promptAssetPaths: string[];
codeAssetPaths: string[];
}

export const agUiStreamingAngularModule: CockpitCapabilityModule = {
id: 'ag-ui-streaming-angular',
manifestIdentity: {
product: 'ag-ui',
section: 'core-capabilities',
topic: 'streaming',
page: 'overview',
language: 'angular',
},
title: 'AG-UI Streaming (Angular)',
docsPath: '/docs/ag-ui/core-capabilities/streaming/overview/angular',
promptAssetPaths: [
'cockpit/ag-ui/streaming/angular/prompts/streaming.md',
],
codeAssetPaths: [
'cockpit/ag-ui/streaming/angular/src/app/streaming.component.ts',
],
};
6 changes: 6 additions & 0 deletions cockpit/ag-ui/streaming/angular/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { StreamingComponent } from './app/streaming.component';

bootstrapApplication(StreamingComponent, appConfig).catch(console.error);
30 changes: 30 additions & 0 deletions cockpit/ag-ui/streaming/angular/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@import "../../../../../libs/design-tokens/src/lib/tokens.css";
@import "tailwindcss";
@source "../../../../../libs/chat/src/";

@theme {
--color-bg: var(--ds-bg);
--color-surface: #ffffff;
--color-accent: var(--ds-accent);
--color-accent-light: var(--ds-accent-light);
--color-text-primary: var(--ds-text-primary);
--color-text-secondary: var(--ds-text-secondary);
--color-text-muted: var(--ds-text-muted);
--color-border: var(--ds-accent-border);
--color-error: #ef4444;
--color-success: #22c55e;
--font-sans: var(--ds-font-sans);
--font-serif: var(--ds-font-serif);
--font-mono: var(--ds-font-mono);
}

*, *::before, *::after { box-sizing: border-box; }

body {
margin: 0;
font-family: var(--ds-font-sans);
background: var(--ds-bg);
color: var(--ds-text-primary);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
11 changes: 11 additions & 0 deletions cockpit/ag-ui/streaming/angular/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"lib": ["es2022", "dom"],
"types": [],
"emitDeclarationOnly": false
},
"files": ["src/main.ts"],
"include": ["src/**/*.ts"]
}
24 changes: 24 additions & 0 deletions cockpit/ag-ui/streaming/angular/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"noPropertyAccessFromIndexSignature": false,
"experimentalDecorators": true,
"module": "preserve",
"emitDeclarationOnly": false,
"composite": false,
"lib": ["es2022", "dom"],
"skipLibCheck": true,
"strict": false
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": false,
"strictInputAccessModifiers": false,
"strictTemplates": false
},
"files": [],
"include": [],
"references": [
{ "path": "./tsconfig.app.json" }
]
}
6 changes: 6 additions & 0 deletions cockpit/ag-ui/streaming/angular/vercel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"buildCommand": "npx nx build cockpit-ag-ui-streaming-angular",
"outputDirectory": "dist/cockpit/ag-ui/streaming/angular/browser",
"framework": null
}
Loading
Loading