Skip to content

Commit 9a85373

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

File tree

5 files changed

+74
-22
lines changed

5 files changed

+74
-22
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: 24 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(value, 'auto') || !_.isEqual(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,11 @@ 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(getFieldValue('agent'), 'auto') &&
1304+
!_.isEqual(getFieldValue('agent'), ['auto'])
1305+
}
12901306
>
12911307
<Radio.Button value="single-node">
12921308
{t('session.launcher.SingleNode')}
@@ -1351,7 +1367,9 @@ const ResourceAllocationFormItems: React.FC<
13511367
}
13521368
disabled={
13531369
derivedClusterSizeMaxLimit === 1 ||
1354-
getFieldValue('agent') !== 'auto'
1370+
(!baiClient.supports('multi-agents') &&
1371+
!_.isEqual(getFieldValue('agent'), 'auto') &&
1372+
!_.isEqual(getFieldValue('agent'), ['auto']))
13551373
}
13561374
sliderProps={{
13571375
marks: {

react/src/hooks/useStartSession.tsx

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,33 @@ export const useStartSession = () => {
181181
preopen_ports: transformPortValuesToNumbers(values.ports),
182182

183183
// Agent selection (optional)
184-
...(baiClient.supports('agent-select') &&
185-
!baiClient?._config?.hideAgents &&
186-
values.agent !== 'auto'
187-
? {
188-
// Filter out undefined values
189-
agent_list: [values.agent].filter(
190-
(agent): agent is string => !!agent,
184+
...(() => {
185+
if (values.agent === undefined) return {};
186+
const agents = _.castArray(values.agent);
187+
if (
188+
!baiClient.supports('agent-select') ||
189+
baiClient?._config?.hideAgents ||
190+
_.isEqual(agents, ['auto']) ||
191+
agents.length === 0
192+
) {
193+
return {};
194+
}
195+
if (
196+
!baiClient.supports('multi-agents') &&
197+
values.cluster_mode === 'multi-node'
198+
) {
199+
// The server now requires agents equivalent to the cluster size.
200+
return {
201+
agent_list: Array.from(
202+
{ length: values.cluster_size },
203+
() => agents[0],
191204
),
192-
}
193-
: undefined),
205+
};
206+
}
207+
return {
208+
agent_list: _.filter(agents, (item) => !!item),
209+
};
210+
})(),
194211
},
195212
},
196213
};

react/src/pages/SessionLauncherPage.tsx

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

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)