Skip to content

Commit 3f28086

Browse files
committed
refactor(contracts): keep the interactor binding module a leaf
Layering R10 counts the largest type-level cycle, and a type-only import of `platform-runtime-operations` from `interactor-operation-binding` pulled the six interactor-backed runtime modules into it (baseline zero). The catalog already imports that type, so the zero-argument group's binder moves there — the one module that already knows both the operations catalog and the interactor sources — and the binding module keeps its two imports. This commit supersedes the binding placement in 267c5c0, which was never pushed.
1 parent e6dddad commit 3f28086

2 files changed

Lines changed: 28 additions & 31 deletions

File tree

‎packages/contracts/src/interactor-operation-binding.ts‎

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import type { DeviceInfo } from '@agent-device/kernel/device';
22
import { AppError } from '@agent-device/kernel/errors';
33
import type { Interactor, RunnerContext } from './interactor-types.ts';
4-
import type {
5-
NoArgumentInteractorInput,
6-
NoArgumentInteractorOperations,
7-
} from './platform-runtime-operations.ts';
84

95
/**
106
* The two ways an interactor-backed operation reaches its mechanics, shared by every binder that
@@ -49,28 +45,3 @@ export function providerInteractorSource(
4945
);
5046
};
5147
}
52-
53-
/**
54-
* Binds the zero-argument interactor operations group: one fact admits each member, one interactor
55-
* call performs it, and the only thing that travels is runner metadata. Each entry point supplies
56-
* its own resolution, so this holds only what they share — the abort check, the runner context, and
57-
* the call. `home` and `app-switcher` carry the same shape in modules written before the shape had a
58-
* name; a new member is one entry in `NoArgumentInteractorOperations` and one line here, plus its
59-
* catalog row, rather than another module and export subpath.
60-
*/
61-
export function bindNoArgumentInteractorOperations(
62-
signal: AbortSignal,
63-
resolveInteractor: (runner: RunnerContext) => Promise<Interactor>,
64-
): NoArgumentInteractorOperations {
65-
return Object.freeze({
66-
actionButton: async (input: NoArgumentInteractorInput) => {
67-
signal.throwIfAborted();
68-
const interactor = await resolveInteractor({
69-
...input.execution,
70-
appBundleId: input.options?.appBundleId,
71-
signal,
72-
});
73-
await interactor.actionButton();
74-
},
75-
});
76-
}

‎packages/contracts/src/interactor-operation-catalog.ts‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,42 @@ import { bindOrientation } from './orientation-runtime.ts';
1010
import { bindSetSetting } from './settings-runtime.ts';
1111
import { bindTvRemote } from './tv-remote-runtime.ts';
1212
import {
13-
bindNoArgumentInteractorOperations,
1413
localInteractorSource,
1514
providerInteractorSource,
1615
type LocalInteractorOperationResolver,
1716
type ProviderInteractorOperationResolver,
1817
} from './interactor-operation-binding.ts';
1918
import type { Interactor, RunnerContext } from './interactor-types.ts';
20-
import type { PlatformRuntimeOperations } from './platform-runtime-operations.ts';
19+
import type {
20+
NoArgumentInteractorOperations,
21+
PlatformRuntimeOperations,
22+
} from './platform-runtime-operations.ts';
2123
import type { RuntimeOperationFact } from './platform-runtime.ts';
2224

25+
/**
26+
* Binds the zero-argument interactor group declared by `NoArgumentInteractorOperations`: one fact
27+
* admits each member, one interactor call performs it, and the only thing that travels is runner
28+
* metadata. Every other catalog row imports a binder from the module that owns that operation's
29+
* contract; this group has no operation-specific mechanism to own, so binding it here is what keeps
30+
* it one row rather than a module, an export subpath, and a facts helper.
31+
*/
32+
function bindNoArgumentInteractorOperations(
33+
signal: AbortSignal,
34+
resolveInteractor: (runner: RunnerContext) => Promise<Interactor>,
35+
): NoArgumentInteractorOperations {
36+
return Object.freeze({
37+
actionButton: async (input) => {
38+
signal.throwIfAborted();
39+
const interactor = await resolveInteractor({
40+
...input.execution,
41+
appBundleId: input.options?.appBundleId,
42+
signal,
43+
});
44+
await interactor.actionButton();
45+
},
46+
});
47+
}
48+
2349
/**
2450
* How a facet turns one resolved interactor into its own typed operations. Every catalog member
2551
* shares this shape, which is what lets one adapter drive all of them: the facet owns what the

0 commit comments

Comments
 (0)