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
1 change: 1 addition & 0 deletions frontend/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2308,6 +2308,7 @@
"runtime": {
"title": "Runtime",
"how": "How it runs",
"native": "Native engine",
"hosted": "Hosted",
"daemon": "On a computer, via the daemon",
"cli": "Single CLI",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2299,6 +2299,7 @@
"runtime": {
"title": "运行环境",
"how": "运行方式",
"native": "原生引擎",
"hosted": "托管运行",
"daemon": "通过守护进程在电脑上运行",
"cli": "单个 CLI",
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/v2/__tests__/V2AgentRuntimeGrants.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,16 @@ test('runtime labels only recognize walked adapters and distinguish daemon from
expect(describeRuntime({ runtimeType: 'webhook', host: 'byo', adapter: 'dsh' })).toEqual({ mode: 'cli', adapter: 'DeepSeek Harness' });
expect(describeRuntime({ runtimeType: 'wrapper', adapter: 'unwalked' })).toEqual({ mode: 'daemon', adapter: null });
expect(describeRuntime({ runtimeType: 'hosted' })).toEqual({ mode: 'hosted', adapter: null });
expect(describeRuntime({ runtimeType: 'native', host: 'cloud' })).toEqual({ mode: 'native', adapter: null });
expect(describeRuntime({ runtimeType: 'webhook', host: 'byo' })).toEqual({ mode: 'unknown', adapter: null });
});

test('shows the native engine for a native agent', async () => {
renderSection({ runtimeType: 'native' });
expect(await screen.findByText('Native engine')).toBeInTheDocument();
expect(screen.queryByText('Hosted')).not.toBeInTheDocument();
});

test('revoked Runtime row offers an active computer and moves in one request', async () => {
axios.get.mockImplementation((url) => Promise.resolve({ data: url.includes('/agent-binding/placement')
? { boundMachineId: 'old', requestedMachineId: null, boundMachineRevoked: true,
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/v2/components/V2AgentRuntimeGrants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@ const WALKED_ADAPTERS: Record<string, string> = {
};
const DAEMON_SETUP_COMMAND = 'npm i -g @commonlyai/cli@latest && commonly login && commonly daemon register && commonly daemon install';

export const describeRuntime = (runtime: Runtime): { mode: 'hosted' | 'daemon' | 'cli' | 'unknown'; adapter: string | null } => {
export const describeRuntime = (runtime: Runtime): { mode: 'native' | 'hosted' | 'daemon' | 'cli' | 'unknown'; adapter: string | null } => {
const type = String(runtime.runtimeType || '').toLowerCase();
const adapterKey = String(runtime.adapter || type).toLowerCase();
const mode = type === 'wrapper' ? (runtime.managed === false ? 'cli' : 'daemon')
: type === 'hosted' || type === 'native' || type === 'internal' || runtime.host === 'cloud' ? 'hosted'
: type === 'native' ? 'native'
: type === 'hosted' || type === 'internal' || runtime.host === 'cloud' ? 'hosted'
: runtime.host === 'byo' && WALKED_ADAPTERS[adapterKey] ? 'cli' : 'unknown';
return { mode, adapter: WALKED_ADAPTERS[adapterKey] || null };
};
Expand Down Expand Up @@ -142,6 +143,7 @@ const V2AgentRuntimeGrants: React.FC<Props> = ({

const details = useMemo(() => describeRuntime(runtime), [runtime]);
const modeLabel = {
native: t('agentManage.runtime.native', { defaultValue: 'Native engine' }),
hosted: t('agentManage.runtime.hosted', { defaultValue: 'Hosted' }),
daemon: t('agentManage.runtime.daemon', { defaultValue: 'On a computer, via the daemon' }),
cli: t('agentManage.runtime.cli', { defaultValue: 'Single CLI' }),
Expand Down
Loading