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
2 changes: 2 additions & 0 deletions src/copilot-shell/packages/cli/src/i18n/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,8 @@ export default {
'User Agreement:': 'User Agreement:',
reviewed: 'reviewed',
'Code Changes:': 'Code Changes:',
'Sandbox Runs:': 'Sandbox Runs:',
'Sandbox Blocked:': 'Sandbox Blocked:',
Performance: 'Performance',
'Wall Time:': 'Wall Time:',
'Agent Active:': 'Agent Active:',
Expand Down
2 changes: 2 additions & 0 deletions src/copilot-shell/packages/cli/src/i18n/locales/zh.js
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,8 @@ export default {
'User Agreement:': '用户同意率:',
reviewed: '已审核',
'Code Changes:': '代码变更:',
'Sandbox Runs:': '沙箱执行:',
'Sandbox Blocked:': '沙箱拦截:',
Performance: '性能',
'Wall Time:': '总耗时:',
'Agent Active:': '代理活跃时间:',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,10 @@ describe('BaseJsonOutputAdapter', () => {
totalLinesAdded: 10,
totalLinesRemoved: 5,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const options: ResultOptions = {
isError: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,10 @@ describe('JsonOutputAdapter', () => {
totalLinesAdded: 10,
totalLinesRemoved: 5,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

adapter.emitResult({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ describe('<SessionSummaryDisplay />', () => {
totalLinesAdded: 42,
totalLinesRemoved: 15,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
Expand All @@ -107,6 +111,10 @@ describe('<SessionSummaryDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

// Pass promptCount = 0 to simulate no messages
Expand Down Expand Up @@ -137,6 +145,10 @@ describe('<SessionSummaryDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(zeroMetrics);
Expand Down Expand Up @@ -104,6 +108,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
Expand Down Expand Up @@ -151,6 +159,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
Expand Down Expand Up @@ -188,6 +200,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
Expand Down Expand Up @@ -226,6 +242,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
Expand All @@ -252,6 +272,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const { lastFrame } = renderWithMockedStats(metrics);
expect(lastFrame()).toMatchSnapshot();
Expand All @@ -272,6 +296,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const { lastFrame } = renderWithMockedStats(metrics);
expect(lastFrame()).toMatchSnapshot();
Expand All @@ -292,6 +320,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const { lastFrame } = renderWithMockedStats(metrics);
expect(lastFrame()).toMatchSnapshot();
Expand All @@ -314,6 +346,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 42,
totalLinesRemoved: 18,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
Expand All @@ -340,6 +376,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
Expand All @@ -350,6 +390,67 @@ describe('<StatsDisplay />', () => {
});
});

describe('Sandbox Display', () => {
it('displays sandbox rows when sandbox counts are non-zero', () => {
const metrics: SessionMetrics = {
models: {},
tools: {
totalCalls: 3,
totalSuccess: 2,
totalFail: 1,
totalDurationMs: 300,
totalDecisions: { accept: 0, reject: 0, modify: 0 },
byName: {},
},
files: {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 5,
totalBlocked: 2,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
const output = lastFrame();

expect(output).toContain('Sandbox Runs:');
expect(output).toContain('5');
expect(output).toContain('Sandbox Blocked:');
expect(output).toContain('2');
expect(output).toMatchSnapshot();
});

it('hides sandbox rows when both counts are zero', () => {
const metrics: SessionMetrics = {
models: {},
tools: {
totalCalls: 1,
totalSuccess: 1,
totalFail: 0,
totalDurationMs: 100,
totalDecisions: { accept: 0, reject: 0, modify: 0 },
byName: {},
},
files: {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

const { lastFrame } = renderWithMockedStats(metrics);
const output = lastFrame();

expect(output).not.toContain('Sandbox Runs:');
expect(output).not.toContain('Sandbox Blocked:');
});
});

describe('Title Rendering', () => {
const zeroMetrics: SessionMetrics = {
models: {},
Expand All @@ -365,6 +466,10 @@ describe('<StatsDisplay />', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};

it('renders the default title when no title prop is provided', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,21 @@ export const StatsDisplay: React.FC<StatsDisplayProps> = ({
</Text>
</StatRow>
)}
{(metrics.sandbox.totalRuns > 0 ||
metrics.sandbox.totalBlocked > 0) && (
<>
<StatRow title={t('Sandbox Runs:')}>
<Text color={theme.text.primary}>
{metrics.sandbox.totalRuns}
</Text>
</StatRow>
<StatRow title={t('Sandbox Blocked:')}>
<Text color={theme.status.error}>
{metrics.sandbox.totalBlocked}
</Text>
</StatRow>
</>
)}
</Section>

<Section title={t('Performance')}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,28 @@ exports[`<StatsDisplay /> > Conditional Rendering Tests > hides User Agreement w
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
`;

exports[`<StatsDisplay /> > Sandbox Display > displays sandbox rows when sandbox counts are non-zero 1`] = `
"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ │
│ Session Stats │
│ │
│ Interaction Summary │
│ Session ID: test-session-id │
│ Tool Calls: 3 ( ✓ 2 x 1 ) │
│ Success Rate: 66.7% │
│ Sandbox Runs: 5 │
│ Sandbox Blocked: 2 │
│ │
│ Performance │
│ Wall Time: 1s │
│ Agent Active: 300ms │
│ » API Time: 0s (0.0%) │
│ » Tool Time: 300ms (100.0%) │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
`;

exports[`<StatsDisplay /> > Title Rendering > renders the custom title when a title prop is provided 1`] = `
"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ │
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ function areMetricsEqual(a: SessionMetrics, b: SessionMetrics): boolean {
return false;
}

// Compare sandbox
if (
a.sandbox.totalRuns !== b.sandbox.totalRuns ||
a.sandbox.totalBlocked !== b.sandbox.totalBlocked
) {
return false;
}

// Compare tools
const toolsA = a.tools;
const toolsB = b.tools;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ describe('computeUsageFromMetrics', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const result = computeUsageFromMetrics(metrics);
expect(result).toEqual({
Expand Down Expand Up @@ -415,6 +419,10 @@ describe('computeUsageFromMetrics', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const result = computeUsageFromMetrics(metrics);
expect(result).toEqual({
Expand Down Expand Up @@ -457,6 +465,10 @@ describe('computeUsageFromMetrics', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const result = computeUsageFromMetrics(metrics);
expect(result).not.toHaveProperty('total_tokens');
Expand Down Expand Up @@ -487,6 +499,10 @@ describe('computeUsageFromMetrics', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const result = computeUsageFromMetrics(metrics);
expect(result).toEqual({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ describe('JsonFormatter', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const formatted = formatter.format(response, stats);
const expected = {
Expand Down Expand Up @@ -210,6 +214,10 @@ describe('JsonFormatter', () => {
totalLinesAdded: 0,
totalLinesRemoved: 0,
},
sandbox: {
totalRuns: 0,
totalBlocked: 0,
},
};
const error: JsonError = {
type: 'ApiError',
Expand Down
Loading
Loading