Skip to content

Commit f9f51f1

Browse files
committed
🤖 feat: add storybook story for auto-compact warning
- Add contextUsage parameter to createAssistantMessage for testing high token usage - Add AutoCompactWarning story showing the indicator at 65% context usage
1 parent c83eb16 commit f9f51f1

File tree

3 files changed

+120
-3
lines changed

3 files changed

+120
-3
lines changed

src/browser/components/CompactionWarning.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const CompactionWarning: React.FC<{
4747
}
4848

4949
return (
50-
<div className="mx-auto -mb-1 w-full max-w-4xl px-[15px] text-right text-[10px]">
50+
<div className="mx-auto mb-1 w-full max-w-4xl px-[15px] text-right text-[10px]">
5151
<button
5252
type="button"
5353
onClick={props.onCompactClick}

src/browser/stories/App.chat.stories.tsx

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,116 @@ export const GenericTool: AppStory = {
456456
},
457457
};
458458

459+
/** Shows auto-compact warning when context usage approaches threshold */
460+
export const AutoCompactWarning: AppStory = {
461+
render: () => (
462+
<AppWithMocks
463+
setup={() =>
464+
setupSimpleChatStory({
465+
workspaceId: "ws-compaction-warning",
466+
messages: [
467+
createUserMessage("msg-1", "Help me set up authentication for this app", {
468+
historySequence: 1,
469+
timestamp: STABLE_TIMESTAMP - 600000,
470+
}),
471+
createAssistantMessage(
472+
"msg-2",
473+
"I'll help you set up authentication. Let me first examine your current project structure and dependencies.",
474+
{
475+
historySequence: 2,
476+
timestamp: STABLE_TIMESTAMP - 580000,
477+
toolCalls: [
478+
createFileReadTool(
479+
"call-1",
480+
"package.json",
481+
'{\n "name": "my-app",\n "dependencies": {\n "express": "^4.18.0",\n "mongoose": "^7.0.0"\n }\n}'
482+
),
483+
],
484+
}
485+
),
486+
createUserMessage("msg-3", "I want to use JWT tokens for the auth", {
487+
historySequence: 3,
488+
timestamp: STABLE_TIMESTAMP - 500000,
489+
}),
490+
createAssistantMessage(
491+
"msg-4",
492+
"Great choice! I'll implement JWT-based authentication. Let me create the auth middleware and user routes.",
493+
{
494+
historySequence: 4,
495+
timestamp: STABLE_TIMESTAMP - 480000,
496+
toolCalls: [
497+
createFileEditTool(
498+
"call-2",
499+
"src/middleware/auth.ts",
500+
"+ import jwt from 'jsonwebtoken';\n+ export const authenticate = (req, res, next) => {\n+ const token = req.headers.authorization?.split(' ')[1];\n+ // ... verification logic\n+ };"
501+
),
502+
],
503+
}
504+
),
505+
createUserMessage("msg-5", "Add password hashing too", {
506+
historySequence: 5,
507+
timestamp: STABLE_TIMESTAMP - 400000,
508+
}),
509+
createAssistantMessage(
510+
"msg-6",
511+
"I'll add bcrypt for secure password hashing. Here's the updated user model with password hashing on save.",
512+
{
513+
historySequence: 6,
514+
timestamp: STABLE_TIMESTAMP - 380000,
515+
toolCalls: [
516+
createTerminalTool("call-3", "bun add bcrypt", "added bcrypt@5.1.0"),
517+
createFileEditTool(
518+
"call-4",
519+
"src/models/user.ts",
520+
"+ import bcrypt from 'bcrypt';\n+ userSchema.pre('save', async function() {\n+ this.password = await bcrypt.hash(this.password, 10);\n+ });"
521+
),
522+
],
523+
}
524+
),
525+
createUserMessage("msg-7", "Now add refresh token support", {
526+
historySequence: 7,
527+
timestamp: STABLE_TIMESTAMP - 300000,
528+
}),
529+
createAssistantMessage(
530+
"msg-8",
531+
"I've implemented refresh token support with secure rotation. The access token expires in 15 minutes and the refresh token in 7 days.",
532+
{
533+
historySequence: 8,
534+
timestamp: STABLE_TIMESTAMP - 280000,
535+
// High context usage to trigger warning (65% of 200k)
536+
contextUsage: { inputTokens: 130000, outputTokens: 5000, totalTokens: 135000 },
537+
}
538+
),
539+
],
540+
})
541+
}
542+
/>
543+
),
544+
play: async ({ canvasElement }: { canvasElement: HTMLElement }) => {
545+
const canvas = within(canvasElement);
546+
547+
// Wait for last assistant message to render (unique text from assistant)
548+
await waitFor(() => {
549+
canvas.getByText(/access token expires in 15 minutes/);
550+
});
551+
552+
// Wait a bit for auto-scroll to settle, then scroll up
553+
await new Promise((r) => setTimeout(r, 100));
554+
const messageWindow = canvasElement.querySelector('[data-testid="message-window"]');
555+
if (messageWindow) {
556+
messageWindow.scrollTop = messageWindow.scrollHeight - messageWindow.clientHeight - 150;
557+
}
558+
},
559+
parameters: {
560+
docs: {
561+
description: {
562+
story:
563+
"Displays the auto-compact warning indicator above the chat input when context usage is approaching the compaction threshold. The indicator shows remaining headroom and is clickable to insert /compact command.",
564+
},
565+
},
566+
},
567+
};
568+
459569
/** Streaming compaction with shimmer effect - tests GPU-accelerated animation */
460570
export const StreamingCompaction: AppStory = {
461571
render: () => (

src/browser/stories/mockFactory.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ export function createAssistantMessage(
203203
model?: string;
204204
reasoning?: string;
205205
toolCalls?: MuxPart[];
206+
/** Custom context usage for testing compaction warning (default: small values) */
207+
contextUsage?: { inputTokens: number; outputTokens: number; totalTokens: number };
206208
}
207209
): ChatMuxMessage {
208210
const parts: MuxPart[] = [];
@@ -213,6 +215,11 @@ export function createAssistantMessage(
213215
if (opts.toolCalls) {
214216
parts.push(...opts.toolCalls);
215217
}
218+
const contextUsage = opts.contextUsage ?? {
219+
inputTokens: 100,
220+
outputTokens: 50,
221+
totalTokens: 150,
222+
};
216223
return {
217224
type: "message",
218225
id,
@@ -222,8 +229,8 @@ export function createAssistantMessage(
222229
historySequence: opts.historySequence,
223230
timestamp: opts.timestamp ?? STABLE_TIMESTAMP,
224231
model: opts.model ?? DEFAULT_MODEL,
225-
usage: { inputTokens: 100, outputTokens: 50, totalTokens: 150 },
226-
contextUsage: { inputTokens: 100, outputTokens: 50, totalTokens: 150 },
232+
usage: contextUsage,
233+
contextUsage,
227234
duration: 1000,
228235
},
229236
};

0 commit comments

Comments
 (0)