Skip to content

Commit 3222230

Browse files
agentfront[bot]frontegg-david
andcommitted
Cherry-pick: feat: add reinitialization support for terminated sessions and improve data injection in weather widget
Cherry-picked from #325 (merged to release/1.0.x) Original commit: 2452586 Co-Authored-By: frontegg-david <69419539+frontegg-david@users.noreply.github.com>
1 parent eda522e commit 3222230

41 files changed

Lines changed: 2057 additions & 1136 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/perf.yml

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,26 @@ concurrency:
1313
jobs:
1414
perf:
1515
runs-on: ubuntu-latest
16-
timeout-minutes: 15
16+
timeout-minutes: 20
1717

1818
strategy:
1919
fail-fast: false
2020
matrix:
21-
project:
22-
- demo-e2e-agents
23-
- demo-e2e-cache
24-
- demo-e2e-codecall
25-
- demo-e2e-config
26-
- demo-e2e-direct
27-
- demo-e2e-elicitation
28-
- demo-e2e-errors
29-
- demo-e2e-hooks
30-
- demo-e2e-multiapp
31-
- demo-e2e-notifications
32-
- demo-e2e-openapi
33-
- demo-e2e-providers
34-
- demo-e2e-public
35-
- demo-e2e-redis
36-
- demo-e2e-remember
37-
- demo-e2e-remote
38-
- demo-e2e-serverless
39-
- demo-e2e-skills
40-
- demo-e2e-standalone
41-
- demo-e2e-transport-recreation
42-
- demo-e2e-ui
21+
chunk:
22+
- index: 0
23+
projects: "demo-e2e-agents,demo-e2e-cache,demo-e2e-codecall"
24+
- index: 1
25+
projects: "demo-e2e-config,demo-e2e-direct,demo-e2e-elicitation"
26+
- index: 2
27+
projects: "demo-e2e-errors,demo-e2e-hooks,demo-e2e-multiapp"
28+
- index: 3
29+
projects: "demo-e2e-notifications,demo-e2e-openapi,demo-e2e-providers"
30+
- index: 4
31+
projects: "demo-e2e-public,demo-e2e-redis,demo-e2e-remember"
32+
- index: 5
33+
projects: "demo-e2e-remote,demo-e2e-serverless,demo-e2e-skills"
34+
- index: 6
35+
projects: "demo-e2e-standalone,demo-e2e-transport-recreation,demo-e2e-ui"
4336

4437
services:
4538
redis:
@@ -85,8 +78,22 @@ jobs:
8578
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8679
continue-on-error: true
8780

88-
- name: Run performance tests (${{ matrix.project }})
89-
run: yarn nx run ${{ matrix.project }}:test:perf
81+
- name: Run performance tests (chunk ${{ matrix.chunk.index }})
82+
run: |
83+
FAILED=0
84+
IFS=',' read -ra PROJECTS <<< "${{ matrix.chunk.projects }}"
85+
for project in "${PROJECTS[@]}"; do
86+
echo "::group::Running perf tests for $project"
87+
if ! yarn nx run "$project":test:perf; then
88+
echo "::error::Performance tests failed for $project"
89+
FAILED=$((FAILED + 1))
90+
fi
91+
echo "::endgroup::"
92+
done
93+
if [ "$FAILED" -gt 0 ]; then
94+
echo "::error::$FAILED project(s) had performance test failures"
95+
exit 1
96+
fi
9097
env:
9198
NODE_OPTIONS: "--expose-gc --max-old-space-size=4096"
9299
REDIS_HOST: localhost
@@ -95,7 +102,7 @@ jobs:
95102
- name: Upload performance report
96103
uses: actions/upload-artifact@v6
97104
with:
98-
name: perf-report-${{ matrix.project }}
105+
name: perf-report-chunk-${{ matrix.chunk.index }}
99106
path: perf-results/
100107
retention-days: 30
101108
if: always()
@@ -115,7 +122,7 @@ jobs:
115122
uses: actions/download-artifact@v5
116123
with:
117124
path: perf-results
118-
pattern: perf-report-*
125+
pattern: perf-report-chunk-*
119126
merge-multiple: true
120127

121128
- name: Write full report to workflow summary

.github/workflows/push.yml

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,15 @@ jobs:
124124
dist/
125125
retention-days: 1
126126

127-
# Discover E2E projects dynamically using Nx tags
127+
# Discover E2E projects dynamically using Nx tags, chunked for API rate limits
128128
discover-e2e:
129129
name: "Discover E2E Projects"
130130
needs: setup
131131
runs-on: ubuntu-latest
132132
permissions:
133133
contents: read
134134
outputs:
135-
matrix: ${{ steps.discover.outputs.projects }}
135+
matrix: ${{ steps.discover.outputs.chunks }}
136136
steps:
137137
- name: Checkout code
138138
uses: actions/checkout@v6
@@ -146,16 +146,23 @@ jobs:
146146
- name: Install dependencies
147147
run: yarn install --frozen-lockfile
148148

149-
- name: Discover E2E projects
149+
- name: Discover E2E projects and create chunks
150150
id: discover
151151
run: |
152152
PROJECTS_JSON=$(npx nx show projects -p tag:type:e2e --json 2>/dev/null | jq -c '.' || echo "[]")
153153
if [ "$PROJECTS_JSON" = "[]" ] || [ "$PROJECTS_JSON" = "null" ]; then
154154
echo "::error::No E2E projects found with tag:type:e2e"
155155
exit 1
156156
fi
157-
echo "Found $(echo $PROJECTS_JSON | jq 'length') E2E projects"
158-
echo "projects=$PROJECTS_JSON" >> $GITHUB_OUTPUT
157+
TOTAL=$(echo $PROJECTS_JSON | jq 'length')
158+
echo "Found $TOTAL E2E projects"
159+
160+
# Chunk projects into groups of 4 to reduce API rate limit pressure
161+
CHUNK_SIZE=4
162+
CHUNKS=$(echo $PROJECTS_JSON | jq -c --argjson n "$CHUNK_SIZE" '[range(0; length; $n) as $i | .[$i:$i+$n]] | to_entries | map({index: .key, projects: .value})')
163+
CHUNK_COUNT=$(echo $CHUNKS | jq 'length')
164+
echo "Created $CHUNK_COUNT chunks of up to $CHUNK_SIZE projects each"
165+
echo "chunks=$CHUNKS" >> $GITHUB_OUTPUT
159166
160167
# Unit tests (depends on build)
161168
unit-tests:
@@ -182,7 +189,7 @@ jobs:
182189
run: yarn install --frozen-lockfile
183190

184191
- name: Download build artifacts
185-
uses: actions/download-artifact@v5
192+
uses: actions/download-artifact@v6
186193
with:
187194
name: dist
188195

@@ -209,16 +216,16 @@ jobs:
209216
retention-days: 1
210217
if-no-files-found: warn
211218

212-
# E2E tests - matrix strategy for parallelization
219+
# E2E tests - chunked matrix strategy to reduce API rate limit pressure
213220
e2e-tests:
214-
name: "E2E Tests (${{ matrix.project }})"
221+
name: "E2E Tests (chunk ${{ matrix.chunk.index }})"
215222
needs: [setup, build, discover-e2e]
216223
runs-on: ubuntu-latest
217-
timeout-minutes: 15
224+
timeout-minutes: 20
218225
strategy:
219226
fail-fast: false
220227
matrix:
221-
project: ${{ fromJson(needs.discover-e2e.outputs.matrix) }}
228+
chunk: ${{ fromJson(needs.discover-e2e.outputs.matrix) }}
222229
env:
223230
NX_DAEMON: "false"
224231
RUN_COVERAGE: ${{ github.ref == 'refs/heads/main' }}
@@ -238,7 +245,7 @@ jobs:
238245
run: yarn install --frozen-lockfile
239246

240247
- name: Download build artifacts
241-
uses: actions/download-artifact@v5
248+
uses: actions/download-artifact@v6
242249
with:
243250
name: dist
244251

@@ -248,35 +255,38 @@ jobs:
248255
- name: Set Nx SHAs
249256
uses: nrwl/nx-set-shas@v5
250257

251-
- name: Run E2E tests (${{ matrix.project }})
258+
- name: Run E2E tests (chunk ${{ matrix.chunk.index }})
252259
id: test
253260
continue-on-error: true
254261
run: |
262+
PROJECTS='${{ join(matrix.chunk.projects, ',') }}'
263+
echo "Running E2E tests for: $PROJECTS"
255264
if [ "$RUN_COVERAGE" = "true" ]; then
256-
npx nx run ${{ matrix.project }}:test --coverage
265+
npx nx run-many -t test --projects="$PROJECTS" --coverage --parallel=1
257266
else
258-
npx nx run ${{ matrix.project }}:test
267+
npx nx run-many -t test --projects="$PROJECTS" --parallel=1
259268
fi
260269
261270
- name: Reset Nx cache on failure
262271
if: steps.test.outcome == 'failure'
263272
run: npx nx reset
264273

265-
- name: Retry E2E tests (${{ matrix.project }})
274+
- name: Retry E2E tests (chunk ${{ matrix.chunk.index }})
266275
if: steps.test.outcome == 'failure'
267276
run: |
277+
PROJECTS='${{ join(matrix.chunk.projects, ',') }}'
268278
if [ "$RUN_COVERAGE" = "true" ]; then
269-
npx nx run ${{ matrix.project }}:test --coverage
279+
npx nx run-many -t test --projects="$PROJECTS" --coverage --parallel=1
270280
else
271-
npx nx run ${{ matrix.project }}:test
281+
npx nx run-many -t test --projects="$PROJECTS" --parallel=1
272282
fi
273283
274284
- name: Upload E2E coverage artifacts
275285
if: env.RUN_COVERAGE == 'true' && always()
276286
uses: actions/upload-artifact@v6
277287
with:
278-
name: e2e-coverage-${{ matrix.project }}
279-
path: coverage/e2e/${{ matrix.project }}/
288+
name: e2e-coverage-chunk-${{ matrix.chunk.index }}
289+
path: coverage/e2e/
280290
retention-days: 1
281291
if-no-files-found: warn
282292

@@ -302,15 +312,15 @@ jobs:
302312
run: yarn install --frozen-lockfile
303313

304314
- name: Download unit coverage artifacts
305-
uses: actions/download-artifact@v5
315+
uses: actions/download-artifact@v6
306316
with:
307317
name: unit-coverage
308318
path: coverage/unit/
309319

310320
- name: Download E2E coverage artifacts
311-
uses: actions/download-artifact@v5
321+
uses: actions/download-artifact@v6
312322
with:
313-
pattern: e2e-coverage-*
323+
pattern: e2e-coverage-chunk-*
314324
path: coverage/e2e/
315325
merge-multiple: true
316326

apps/demo/src/apps/weather/tools/get-weather.tool.tsx

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
* and other UI-capable hosts.
88
*/
99

10-
import React from 'react';
1110
import { Tool, ToolContext } from '@frontmcp/sdk';
12-
import { Card, Badge } from '@frontmcp/ui/components';
1311
import { z } from 'zod';
1412

1513
// Define input/output schemas
@@ -29,45 +27,8 @@ const outputSchema = z.object({
2927
});
3028

3129
// Infer types from schemas for proper typing
32-
type WeatherInput = z.infer<z.ZodObject<typeof inputSchema>>;
33-
type WeatherOutput = z.infer<typeof outputSchema>;
34-
35-
// Weather condition icon mapping (using emoji for simplicity)
36-
const iconMap: Record<string, string> = {
37-
sunny: '☀️',
38-
cloudy: '☁️',
39-
rainy: '🌧️',
40-
snowy: '❄️',
41-
stormy: '⛈️',
42-
windy: '💨',
43-
foggy: '🌫️',
44-
};
45-
46-
function WeatherWidget({ output }: { output: WeatherOutput }) {
47-
const tempSymbol = output.units === 'celsius' ? '°C' : '°F';
48-
const weatherIcon = iconMap[output.icon] || '🌤️';
49-
const badgeVariant = output.conditions === 'sunny' ? 'success' : output.conditions === 'rainy' ? 'info' : 'default';
50-
51-
return (
52-
<Card title={output.location} subtitle="Current Weather" elevation={2}>
53-
<div style={{ textAlign: 'center', padding: '24px 0' }}>
54-
<div style={{ fontSize: '3.75rem', marginBottom: '8px' }}>{weatherIcon}</div>
55-
<div style={{ fontSize: '3rem', fontWeight: 300, marginBottom: '8px' }}>
56-
{output.temperature}
57-
{tempSymbol}
58-
</div>
59-
<div style={{ display: 'flex', justifyContent: 'center' }}>
60-
<Badge label={output.conditions} variant={badgeVariant} />
61-
</div>
62-
</div>
63-
<div style={{ marginTop: '16px' }}>
64-
<div>Humidity: {output.humidity}%</div>
65-
<div>Wind Speed: {output.windSpeed} km/h</div>
66-
<div>Units: {output.units === 'celsius' ? 'Celsius' : 'Fahrenheit'}</div>
67-
</div>
68-
</Card>
69-
);
70-
}
30+
export type WeatherInput = z.infer<z.ZodObject<typeof inputSchema>>;
31+
export type WeatherOutput = z.infer<typeof outputSchema>;
7132

7233
@Tool({
7334
name: 'get_weather',
@@ -84,7 +45,7 @@ function WeatherWidget({ output }: { output: WeatherOutput }) {
8445
displayMode: 'inline',
8546
servingMode: 'static',
8647
uiType: 'react',
87-
template: WeatherWidget,
48+
template: { file: 'apps/demo/src/apps/weather/tools/get-weather.ui.tsx' },
8849
},
8950
codecall: {
9051
visibleInListTools: true,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
export const Card = ({
2+
title,
3+
subtitle,
4+
children,
5+
}: {
6+
title?: string;
7+
subtitle?: string;
8+
elevation?: number;
9+
children?: React.ReactNode;
10+
}) => {
11+
return (
12+
<div style={{ border: '1px solid #ccc', borderRadius: '8px', padding: '16px', maxWidth: '400px' }}>
13+
<h2>{title}</h2>
14+
<h4 style={{ color: '#666' }}>{subtitle}</h4>
15+
{children}
16+
</div>
17+
);
18+
};
19+
20+
export const Badge = ({ label, variant }: { label: string; variant: 'success' | 'info' | 'default' }) => {
21+
return (
22+
<span
23+
style={{
24+
backgroundColor: variant === 'success' ? '#4caf50' : variant === 'info' ? '#2196f3' : '#9e9e9e',
25+
color: 'white',
26+
padding: '4px 8px',
27+
borderRadius: '4px',
28+
fontSize: '0.875rem',
29+
fontWeight: 'bold',
30+
}}
31+
>
32+
{label}
33+
</span>
34+
);
35+
};

0 commit comments

Comments
 (0)