Skip to content
Closed
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
225 changes: 1 addition & 224 deletions src/components/chat/utils/__tests__/sessionContextSummary.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { describe, expect, it } from 'vitest';

import {
deriveSessionContextSummary,
mergeDistinctChatMessages,
resolveSessionContextProjectRoot,
} from '../sessionContextSummary';
import { deriveSessionContextSummary, mergeDistinctChatMessages } from '../sessionContextSummary';

describe('deriveSessionContextSummary', () => {
const projectRoot = '/workspace/demo';
Expand Down Expand Up @@ -106,225 +102,6 @@ describe('deriveSessionContextSummary', () => {
expect(summary.outputFiles[0].relativePath).toBe('outputs/report.md');
expect(summary.outputFiles[0].unread).toBe(true);
});

it('recognizes Codex shell reads, plans, patch outputs, and web actions', () => {
const messages = [
{
type: 'assistant',
timestamp: '2026-03-30T05:18:28.000Z',
isToolUse: true,
toolName: 'Bash',
toolInput: JSON.stringify({
command: "sed -n '1,200p' src/components/chat/utils/sessionContextSummary.ts",
workdir: projectRoot,
}),
toolResult: {
content: 'const summary = true;',
isError: false,
},
},
{
type: 'assistant',
timestamp: '2026-03-30T05:19:00.000Z',
isToolUse: true,
toolName: 'UpdatePlan',
toolInput: JSON.stringify({
plan: [
{ step: 'Normalize Codex history', status: 'in_progress' },
{ step: 'Expand session summary', status: 'pending' },
],
}),
},
{
type: 'assistant',
timestamp: '2026-03-30T05:20:00.000Z',
isToolUse: true,
toolName: 'Edit',
toolInput: JSON.stringify({
file_path: 'src/components/chat/utils/sessionContextSummary.ts',
file_paths: [
'src/components/chat/utils/sessionContextSummary.ts',
'docs/plan.md',
],
}),
toolResult: {
content: 'Success',
isError: false,
toolUseResult: {
changes: {
'src/components/chat/utils/sessionContextSummary.ts': { type: 'update' },
'docs/plan.md': { type: 'add' },
},
},
},
},
{
type: 'assistant',
timestamp: '2026-03-30T05:21:00.000Z',
isToolUse: true,
toolName: 'WebSearch',
toolInput: JSON.stringify({ query: 'Codex session context panel' }),
},
{
type: 'assistant',
timestamp: '2026-03-30T05:21:30.000Z',
isToolUse: true,
toolName: 'OpenPage',
toolInput: JSON.stringify({ url: 'https://developers.openai.com/api/docs' }),
},
{
type: 'assistant',
timestamp: '2026-03-30T05:22:00.000Z',
isToolUse: true,
toolName: 'FindInPage',
toolInput: JSON.stringify({
url: 'https://developers.openai.com/api/docs',
pattern: 'session',
}),
},
] as any;

const summary = deriveSessionContextSummary(messages, projectRoot);

expect(summary.contextFiles.some((item) => item.relativePath === 'src/components/chat/utils/sessionContextSummary.ts')).toBe(true);
expect(summary.outputFiles.map((item) => item.relativePath).sort()).toEqual([
'docs/plan.md',
'src/components/chat/utils/sessionContextSummary.ts',
]);
expect(summary.tasks.some((item) => item.label === 'Normalize Codex history' && item.kind === 'todo')).toBe(true);
expect(summary.tasks.some((item) => item.label === 'Codex session context panel')).toBe(true);
expect(summary.tasks.some((item) => item.label === 'https://developers.openai.com/api/docs')).toBe(true);
expect(summary.tasks.some((item) => item.label === 'session')).toBe(true);
});

it('ignores dotted shell fragments that are not real file paths', () => {
const messages = [
{
type: 'assistant',
timestamp: '2026-03-31T12:00:00.000Z',
isToolUse: true,
toolName: 'Bash',
toolInput: JSON.stringify({
command: "jq '.sections.survey.synthesis_summary, .sections.survey.open_gaps' pipeline/docs/research_brief.json",
workdir: projectRoot,
}),
toolResult: {
content: '',
isError: false,
},
},
] as any;

const summary = deriveSessionContextSummary(messages, projectRoot);
const contextPaths = summary.contextFiles.map((item) => item.relativePath);

expect(contextPaths).toContain('pipeline/docs/research_brief.json');
expect(contextPaths.some((path) => path.includes('sections.survey'))).toBe(false);
expect(contextPaths.some((path) => path.includes('open_gaps'))).toBe(false);
});

it('strips trailing punctuation from real paths and rejects slash-delimited prose fragments', () => {
const messages = [
{
type: 'assistant',
timestamp: '2026-03-31T12:05:00.000Z',
isToolUse: true,
toolName: 'Bash',
toolInput: JSON.stringify({
command: 'cat ./pipeline/docs/research_brief.json. ./Survey/reports/model_dataset_inventory.json. 3.0/GPT-5.3.',
workdir: projectRoot,
}),
toolResult: {
content: 'Wrote ./pipeline/tasks/tasks.json.',
isError: false,
},
},
] as any;

const summary = deriveSessionContextSummary(messages, projectRoot);
const contextPaths = summary.contextFiles.map((item) => item.relativePath).sort();

expect(contextPaths).toContain('pipeline/docs/research_brief.json');
expect(contextPaths).toContain('Survey/reports/model_dataset_inventory.json');
expect(contextPaths).toContain('pipeline/tasks/tasks.json');
expect(contextPaths.some((path) => path.endsWith('.'))).toBe(false);
expect(contextPaths).not.toContain('3.0/GPT-5.3.');
expect(contextPaths).not.toContain('3.0/GPT-5.3');
});

it('does not turn slash-delimited prose into shell directories', () => {
const messages = [
{
type: 'assistant',
timestamp: '2026-03-31T12:10:00.000Z',
isToolUse: true,
toolName: 'Bash',
toolInput: JSON.stringify({
command: 'python analyze.py cost/latency GeneAgent/BioAgents/GeneGPT HealthBench/MedAgentBench ./Survey/reports',
workdir: projectRoot,
}),
toolResult: {
content: 'Compared GPT-5.3. with cost/latency tradeoffs.',
isError: false,
},
},
] as any;

const summary = deriveSessionContextSummary(messages, projectRoot);
const directoryLabels = summary.directories.map((item) => item.label);
const contextPaths = summary.contextFiles.map((item) => item.relativePath);

expect(directoryLabels).toContain('Survey/reports');
expect(directoryLabels).not.toContain('cost/latency');
expect(directoryLabels).not.toContain('GeneAgent/BioAgents/GeneGPT');
expect(directoryLabels).not.toContain('HealthBench/MedAgentBench');
expect(contextPaths).not.toContain('cost/latency');
expect(contextPaths).not.toContain('GeneAgent/BioAgents/GeneGPT');
expect(contextPaths).not.toContain('HealthBench/MedAgentBench');
expect(contextPaths).not.toContain('GPT-5.3.');
expect(contextPaths).not.toContain('GPT-5.3');
});

it('prefers session workdir over an unrelated project root when normalizing paths', () => {
const wrongProjectRoot = '/workspace/demo';
const sessionRoot = '/home/testuser/projects/experiment-2026';
const messages = [
{
type: 'assistant',
timestamp: '2026-03-31T12:15:00.000Z',
isToolUse: true,
toolName: 'Bash',
toolInput: JSON.stringify({
command: `cat ${sessionRoot}/instance.json ./instance.json`,
workdir: sessionRoot,
}),
toolResult: {
content: '',
isError: false,
},
},
{
type: 'assistant',
timestamp: '2026-03-31T12:16:00.000Z',
isToolUse: true,
toolName: 'LS',
toolInput: JSON.stringify({
path: `${sessionRoot}/analysis`,
}),
},
] as any;

expect(resolveSessionContextProjectRoot(messages, wrongProjectRoot)).toBe(sessionRoot);

const summary = deriveSessionContextSummary(messages, wrongProjectRoot);
const contextPaths = summary.contextFiles.map((item) => item.relativePath);
const directoryLabels = summary.directories.map((item) => item.label);

expect(contextPaths).toEqual(['instance.json']);
expect(directoryLabels).toEqual(['analysis']);
expect(contextPaths.some((path) => path.startsWith('/Users/'))).toBe(false);
expect(directoryLabels.some((label) => label.startsWith('/Users/'))).toBe(false);
});
});

describe('mergeDistinctChatMessages', () => {
Expand Down
Loading
Loading