mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-08-29 10:52:26 +00:00
119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
|
|
|
import { selectBottomBoxControl } from '@/components/ChatBox/BottomBox/controlArbitration';
|
|
import type {
|
|
BottomBoxApprovalVariant,
|
|
BottomBoxInputVariant,
|
|
BottomBoxRunControlVariant,
|
|
} from '@/components/ChatBox/BottomBox/types';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
|
|
function approvalVariant(): BottomBoxApprovalVariant {
|
|
return {
|
|
kind: 'approval',
|
|
header: { title: 'Allow this action?' },
|
|
options: [{ scope: 'once', label: 'Approve once' }],
|
|
onApprove: vi.fn(),
|
|
onReject: vi.fn(),
|
|
};
|
|
}
|
|
|
|
function runControlVariant(): BottomBoxRunControlVariant {
|
|
return {
|
|
kind: 'run_control',
|
|
header: { title: 'Run interrupted' },
|
|
runId: 'run-1',
|
|
state: 'interrupted',
|
|
onResume: vi.fn(),
|
|
onCancel: vi.fn(),
|
|
};
|
|
}
|
|
|
|
describe('BottomBox control arbitration', () => {
|
|
it('gives a pending human interaction priority over Run controls and the composer', () => {
|
|
const humanInteractionVariant = approvalVariant();
|
|
const selection = selectBottomBoxControl({
|
|
humanInteractionVariant,
|
|
runControlVariant: runControlVariant(),
|
|
composerVariant: 'input',
|
|
});
|
|
|
|
expect(selection).toEqual({
|
|
variant: humanInteractionVariant,
|
|
source: 'human_interaction',
|
|
isControlled: true,
|
|
});
|
|
});
|
|
|
|
it('gives Run controls priority over the composer', () => {
|
|
const runControl = runControlVariant();
|
|
const selection = selectBottomBoxControl({
|
|
runControlVariant: runControl,
|
|
composerVariant: 'input',
|
|
});
|
|
|
|
expect(selection).toEqual({
|
|
variant: runControl,
|
|
source: 'run_control',
|
|
isControlled: true,
|
|
});
|
|
});
|
|
|
|
it('preserves a decorated legacy input composer and otherwise uses the normal composer', () => {
|
|
const composerVariant: BottomBoxInputVariant = {
|
|
kind: 'input',
|
|
header: {
|
|
eyebrow: 'Input required',
|
|
title: 'Which output tone should I use?',
|
|
},
|
|
};
|
|
|
|
expect(selectBottomBoxControl({ composerVariant })).toEqual({
|
|
variant: composerVariant,
|
|
source: 'composer',
|
|
isControlled: false,
|
|
});
|
|
expect(selectBottomBoxControl({})).toEqual({
|
|
variant: 'input',
|
|
source: 'composer',
|
|
isControlled: false,
|
|
});
|
|
});
|
|
|
|
it('uses identical control authority for every event-native timeline style', () => {
|
|
const humanInteractionVariant = approvalVariant();
|
|
const runControl = runControlVariant();
|
|
const styles = ['normal', 'detailed', 'summarised'] as const;
|
|
|
|
const selections = styles.map(() =>
|
|
selectBottomBoxControl({
|
|
humanInteractionVariant,
|
|
runControlVariant: runControl,
|
|
composerVariant: 'input',
|
|
})
|
|
);
|
|
|
|
expect(selections.map((selection) => selection.variant)).toEqual([
|
|
humanInteractionVariant,
|
|
humanInteractionVariant,
|
|
humanInteractionVariant,
|
|
]);
|
|
expect(selections.map((selection) => selection.source)).toEqual([
|
|
'human_interaction',
|
|
'human_interaction',
|
|
'human_interaction',
|
|
]);
|
|
});
|
|
});
|