Skip to content

Commit b790279

Browse files
authored
refactor(runtime): own provider-device admission behind a typed capability (#2556)
Ten daemon files imported isActiveProviderDevice from src/provider-device-runtime.ts, so the daemon read provider runtime ownership mechanics directly from twelve sites (ten daemon, one daemon runtime composition, one src/core). The daemon now consumes a named capability: src/daemon/provider-device-admission.ts declares ProviderDeviceAdmission with the one fact the daemon decides on, defaults to the no-provider state every un-composed process already sees, and is installed by root composition where the provider request providers are already composed. The ten leaf call sites change only their import specifier; the predicate keeps its name, its per-call read, and the request-scoped ALS behaviour underneath it. src/core/interactors.ts keeps its edge: it also needs getProviderDeviceInteractor and sits below the daemon, so it cannot consume the daemon's seam. Part of #2541
1 parent 4e8f367 commit b790279

26 files changed

Lines changed: 178 additions & 25 deletions
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { afterEach, beforeEach, expect, test } from 'vitest';
2+
import type { DeviceInfo } from '@agent-device/kernel/device';
3+
import {
4+
installProviderDeviceAdmission,
5+
isActiveProviderDevice,
6+
providerDeviceAdmission,
7+
} from '../provider-device-admission.ts';
8+
9+
const providerDevice = { id: 'provider-1', name: 'Cloud iPhone' } as unknown as DeviceInfo;
10+
const localDevice = { id: 'local-1', name: 'iPhone 16' } as unknown as DeviceInfo;
11+
12+
let previous = providerDeviceAdmission();
13+
14+
beforeEach(() => {
15+
previous = providerDeviceAdmission();
16+
});
17+
18+
afterEach(() => {
19+
installProviderDeviceAdmission(previous);
20+
});
21+
22+
test('an un-composed process treats every device as local', () => {
23+
installProviderDeviceAdmission({ isActive: () => false });
24+
expect(isActiveProviderDevice(providerDevice)).toBe(false);
25+
expect(isActiveProviderDevice(localDevice)).toBe(false);
26+
});
27+
28+
test('the installed admission is what the daemon decides on', () => {
29+
installProviderDeviceAdmission({ isActive: (device) => device.id === 'provider-1' });
30+
expect(isActiveProviderDevice(providerDevice)).toBe(true);
31+
expect(isActiveProviderDevice(localDevice)).toBe(false);
32+
});
33+
34+
test('the fact is read per call, so a request-scoped scope stays live', () => {
35+
let owned = false;
36+
installProviderDeviceAdmission({ isActive: () => owned });
37+
expect(isActiveProviderDevice(providerDevice)).toBe(false);
38+
owned = true;
39+
expect(isActiveProviderDevice(providerDevice)).toBe(true);
40+
});

src/daemon/__tests__/request-router-android-modal.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ import {
1616
import type { SessionState } from '../session-state.ts';
1717
import { LeaseRegistry } from '../lease-registry.ts';
1818
import { makeSessionStore } from '../../__tests__/test-utils/store-factory.ts';
19-
import { createProviderDeviceRuntimeRequestProviders } from '../../provider-device-runtime.ts';
19+
import {
20+
createProviderDeviceRuntimeRequestProviders,
21+
isActiveProviderDevice,
22+
} from '../../provider-device-runtime.ts';
23+
import { installProviderDeviceAdmission } from '../provider-device-admission.ts';
24+
25+
// Root composition installs the daemon's provider-device admission; this test composes the
26+
// request providers the same way, so it installs the fact the same way.
27+
installProviderDeviceAdmission({ isActive: isActiveProviderDevice });
2028
import type { ProviderDeviceRuntime } from '@agent-device/contracts/device';
2129
import { makeTestScreenRecordingResource } from '../../__tests__/test-utils/screen-recording-live-handle.ts';
2230
import { androidObservation } from '../../platform-runtime.ts';

src/daemon/__tests__/selector-capture-fixture.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
snapshotRuntimeOperationFacts,
1313
} from '@agent-device/contracts/snapshot-runtime';
1414
import { deviceShape, type DeviceInfo } from '@agent-device/kernel/device';
15-
import { isActiveProviderDevice } from '../../provider-device-runtime.ts';
15+
import { isActiveProviderDevice } from '../provider-device-admission.ts';
1616
import type { BindDeviceRuntime, InspectDeviceRuntimeFacts } from '../request-runtime-binding.ts';
1717
import { unavailableDeviceRuntimeGateway } from './test-device-runtime-gateway.ts';
1818

src/daemon/__tests__/session-device-resolution.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from '../session-device-resolution.ts';
99
import { appleSessionObservation } from '../../platform-runtime-apple-resources.ts';
1010
import { resolveTargetDevice } from '@agent-device/device-selection/dispatch-resolve';
11-
import { isActiveProviderDevice } from '../../provider-device-runtime.ts';
11+
import { isActiveProviderDevice } from '../provider-device-admission.ts';
1212
import { ensureDeviceReady } from '../device-ready.ts';
1313

1414
vi.mock('../../platform-runtime-apple-resources.ts', async (importOriginal) => ({
@@ -18,7 +18,7 @@ vi.mock('../../platform-runtime-apple-resources.ts', async (importOriginal) => (
1818
vi.mock('@agent-device/device-selection/dispatch-resolve', () => ({
1919
resolveTargetDevice: vi.fn(),
2020
}));
21-
vi.mock('../../provider-device-runtime.ts', () => ({
21+
vi.mock('../provider-device-admission.ts', () => ({
2222
isActiveProviderDevice: vi.fn(() => false),
2323
}));
2424
vi.mock('../device-ready.ts', () => ({

src/daemon/__tests__/snapshot-runtime-fixture.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
import { applePlugin } from '@agent-device/platform-apple';
3434
import { type DispatchContext } from '../../core/dispatch-context.ts';
3535
import { getRequestSignal } from '@agent-device/host-kit/request';
36-
import { isActiveProviderDevice } from '../../provider-device-runtime.ts';
36+
import { isActiveProviderDevice } from '../provider-device-admission.ts';
3737
import type { BindDeviceRuntime, InspectDeviceRuntimeFacts } from '../request-runtime-binding.ts';
3838
import { unavailableDeviceRuntimeGateway } from './test-device-runtime-gateway.ts';
3939
import { writeSolidPng } from './screenshot-runtime-fixture.ts';

src/daemon/android-foreground-surface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { AndroidObservationAdapter } from '@agent-device/contracts/android-observation';
22
import { AppError } from '@agent-device/kernel/errors';
3-
import { isActiveProviderDevice } from '../provider-device-runtime.ts';
3+
import { isActiveProviderDevice } from './provider-device-admission.ts';
44
import type { SessionState } from './session-state.ts';
55

66
export type AndroidEscapeSurface = {

src/daemon/android-system-dialog.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { centerOfRect, type SnapshotNode } from '@agent-device/kernel/snapshot';
1010
import { isSnapshotNodeInteractionBlocked } from '@agent-device/capture-kit/snapshot-occlusion';
1111
import { expireRefFrame } from './ref-frame.ts';
1212
import type { SessionState } from './session-state.ts';
13-
import { isActiveProviderDevice } from '../provider-device-runtime.ts';
13+
import { isActiveProviderDevice } from './provider-device-admission.ts';
1414

1515
const ANDROID_BLOCKING_MODAL_PATTERN = /\bis(?:n(?:'|'|')?t| not)\s+responding\b/i;
1616
const ANDROID_CLOSE_APP_PATTERN = /^close app$/i;

src/daemon/device-ready.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { DeviceInfo } from '@agent-device/kernel/device';
22
import { ensureLocalPlatformDeviceReady } from '../platform-runtime-device-ready.ts';
3-
import { isActiveProviderDevice } from '../provider-device-runtime.ts';
3+
import { isActiveProviderDevice } from './provider-device-admission.ts';
44
import { createTtlMemo } from '@agent-device/kernel/ttl-memo';
55

66
// Exported so unit tests can assert TTL behavior without duplicating the value.

src/daemon/direct-ios-selector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { isIosFamily } from '@agent-device/kernel/device';
22
import type { SnapshotNode } from '@agent-device/kernel/snapshot';
3-
import { isActiveProviderDevice } from '../provider-device-runtime.ts';
3+
import { isActiveProviderDevice } from './provider-device-admission.ts';
44
import { isPostGestureStabilizationPending } from './deferred-interaction-outcome.ts';
55
import type { SessionState } from './session-state.ts';
66
import { readSimpleSelectorTarget } from '@agent-device/selectors';

src/daemon/handlers/__tests__/session-doctor-warmup.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { beforeEach, expect, test, vi } from 'vitest';
22
import type { DeviceInfo } from '@agent-device/kernel/device';
3-
import { isActiveProviderDevice } from '../../../provider-device-runtime.ts';
3+
import { isActiveProviderDevice } from '../../provider-device-admission.ts';
44
import { handleDoctorCommand } from '../session-doctor.ts';
55
import { createHostDiagnostics } from '../../../platform-runtime-host-diagnostics.ts';
66
import { makeSessionStore } from '../../../__tests__/test-utils/store-factory.ts';
@@ -28,7 +28,7 @@ vi.mock('../session-doctor-app.ts', () => ({
2828
vi.mock('../session-doctor-metro.ts', () => ({
2929
probeMetro: vi.fn(async () => ({ id: 'metro', status: 'pass', summary: 'mocked' })),
3030
}));
31-
vi.mock('../../../provider-device-runtime.ts', () => ({
31+
vi.mock('../../provider-device-admission.ts', () => ({
3232
isActiveProviderDevice: vi.fn(() => false),
3333
}));
3434

0 commit comments

Comments
 (0)