Skip to content

Commit 5313409

Browse files
committed
feat(FR-1448): allow user to select multi agents when creating multi-node session
1 parent d5a042b commit 5313409

File tree

6 files changed

+58
-18
lines changed

6 files changed

+58
-18
lines changed

react/src/components/AgentSelect.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import React, { useDeferredValue, useState } from 'react';
99
import { useTranslation } from 'react-i18next';
1010
import { graphql, useLazyLoadQuery } from 'react-relay';
1111

12-
interface Props extends SelectProps {
12+
interface Props extends Omit<SelectProps, 'options'> {
1313
autoSelectDefault?: boolean;
1414
fetchKey?: string;
1515
resourceGroup?: string | null;
@@ -122,19 +122,33 @@ const AgentSelect: React.FC<Props> = ({
122122
: undefined;
123123
return (
124124
<Select
125-
onChange={(value, option) => {
126-
setValue(value, option);
127-
}}
128125
loading={searchStr !== deferredSearchStr}
129126
filterOption={false}
130127
showSearch
131128
searchValue={searchStr}
132129
onSearch={(v) => {
133130
setSearchStr(v);
134131
}}
135-
{...selectProps}
136-
value={value}
137132
options={filterOutEmpty([autoSelectIfMatch, ...agentOptions])}
133+
//override props.onChange and props.value, it is handled by useControllableValue
134+
{..._.omit(selectProps, ['value', 'onChange'])}
135+
onChange={(value: unknown, option) => {
136+
if (
137+
selectProps.mode === 'multiple' &&
138+
_.isArray(value) &&
139+
_.isArray(option)
140+
) {
141+
if (_.last(value) === 'auto' || value.length === 0) {
142+
value = ['auto'];
143+
option = _.last(option);
144+
} else if (value[0] === 'auto' && value.length > 1) {
145+
value = value.slice(1);
146+
option = option.slice(1);
147+
}
148+
}
149+
setValue(value, option);
150+
}}
151+
value={value}
138152
/>
139153
);
140154
};

react/src/components/SessionFormItems/ResourceAllocationFormItems.tsx

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export const RESOURCE_ALLOCATION_INITIAL_FORM_VALUES: DeepPartial<ResourceAlloca
4646
cluster_mode: 'single-node',
4747
cluster_size: 1,
4848
enabledAutomaticShmem: true,
49-
agent: 'auto',
49+
agent: ['auto'],
5050
};
5151

5252
export const isMinOversMaxValue = (min: number, max: number) => {
@@ -67,7 +67,7 @@ export interface ResourceAllocationFormValue {
6767
cluster_size: number;
6868
enabledAutomaticShmem: boolean;
6969
allocationPreset?: string;
70-
agent?: string;
70+
agent?: string[] | string;
7171
}
7272

7373
export type MergedResourceAllocationFormValue = ResourceAllocationFormValue &
@@ -1233,14 +1233,26 @@ const ResourceAllocationFormItems: React.FC<
12331233
<AgentSelect
12341234
resourceGroup={currentResourceGroupInForm}
12351235
fetchKey={agentFetchKey}
1236+
mode={
1237+
baiClient.supports('multi-agents') ? 'multiple' : undefined
1238+
}
1239+
labelRender={
1240+
baiClient.supports('multi-agents')
1241+
? ({ label, value }) => {
1242+
return value === 'auto' ? label : value;
1243+
}
1244+
: undefined
1245+
}
12361246
onChange={(value) => {
1237-
if (value !== 'auto') {
1247+
if (
1248+
!baiClient.supports('multi-agents') &&
1249+
!_.isEqual(_.castArray(value), ['auto'])
1250+
) {
12381251
form.setFieldsValue({
12391252
cluster_mode: 'single-node',
12401253
cluster_size: 1,
12411254
});
12421255
}
1243-
// TODO: set cluster mode to single node and cluster size to 1 when agent value is not "auto"
12441256
}}
12451257
></AgentSelect>
12461258
</Form.Item>
@@ -1286,7 +1298,12 @@ const ResourceAllocationFormItems: React.FC<
12861298
onChange={() => {
12871299
form.validateFields().catch(() => {});
12881300
}}
1289-
disabled={getFieldValue('agent') !== 'auto'}
1301+
disabled={
1302+
!baiClient.supports('multi-agents') &&
1303+
!_.isEqual(_.castArray(getFieldValue('agent')), [
1304+
'auto',
1305+
])
1306+
}
12901307
>
12911308
<Radio.Button value="single-node">
12921309
{t('session.launcher.SingleNode')}
@@ -1351,7 +1368,11 @@ const ResourceAllocationFormItems: React.FC<
13511368
}
13521369
disabled={
13531370
derivedClusterSizeMaxLimit === 1 ||
1354-
getFieldValue('agent') !== 'auto'
1371+
(!baiClient.supports('multi-agents') &&
1372+
!_.isEqual(
1373+
_.castArray(getFieldValue('agent')),
1374+
['auto'],
1375+
))
13551376
}
13561377
sliderProps={{
13571378
marks: {

react/src/components/SessionLauncherPreview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ const SessionLauncherPreview: React.FC<{
523523
{baiClient.supports('agent-select') &&
524524
!baiClient?._config?.hideAgents && (
525525
<Descriptions.Item label={t('session.launcher.AgentNode')}>
526-
{form.getFieldValue('agent') ||
526+
{_.castArray(form.getFieldValue('agent')).join(', ') ||
527527
t('session.launcher.AutoSelect')}
528528
</Descriptions.Item>
529529
)}

react/src/hooks/useStartSession.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,14 @@ export const useStartSession = () => {
251251
// Agent selection (optional)
252252
...(baiClient.supports('agent-select') &&
253253
!baiClient?._config?.hideAgents &&
254-
values.agent !== 'auto'
254+
values.agent !== undefined &&
255+
!_.isEqual(values.agent, ['auto'])
255256
? {
256257
// Filter out undefined values
257-
agent_list: [values.agent].filter(
258-
(agent): agent is string => !!agent,
259-
),
258+
agent_list: _.chain(values.agent)
259+
.castArray()
260+
.filter((agent): agent is string => !!agent)
261+
.value(),
260262
}
261263
: undefined),
262264
},

react/src/pages/SessionLauncherPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,7 @@ const SessionLauncherPage = () => {
12781278
command: undefined,
12791279
scheduleDate: undefined,
12801280
},
1281-
agent: 'auto', // Add the missing 'agent' property
1281+
agent: ['auto'], // Add the missing 'agent' property
12821282
} as SessionLauncherFormData,
12831283
formValue,
12841284
);

src/lib/backend.ai-client-esm.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,9 @@ class Client {
825825
if (this.isManagerVersionCompatibleWith('25.15.0')) {
826826
this._features['agent-stats'] = true;
827827
}
828+
if (this.isManagerVersionCompatibleWith('25.16.0')) {
829+
this._features['multi-agents'] = true;
830+
}
828831
}
829832

830833
/**

0 commit comments

Comments
 (0)