Skip to content
Open
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
14 changes: 11 additions & 3 deletions packages/askui-nodejs/src/execution/agent-os/agent-os-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class AgentOsClient implements DeviceClient {

private displayId = 1;

constructor(public url: string) {}
constructor(public url: string, private useHttpProxy: boolean = false) {}

private static buildControllerApiConstructor(): grpc.ServiceClientConstructor {
const packageDefinition = protoLoader.loadSync(
Expand Down Expand Up @@ -118,9 +118,17 @@ export class AgentOsClient implements DeviceClient {
return `${address}:${AgentOsClient.DEFAULT_PORT}`;
}

private static async openChannel(address: string): Promise<grpc.Client> {
private static async openChannel(
address: string,
useHttpProxy: boolean,
): Promise<grpc.Client> {
const ControllerApi = AgentOsClient.buildControllerApiConstructor();
const client = new ControllerApi(address, grpc.credentials.createInsecure(), {
// By default, the AgentOS (local or remote) is reached directly because
// grpc-js would otherwise honor grpc_proxy/https_proxy and corporate
// proxies generally cannot tunnel gRPC (CONNECT answered with
// redirects/auth pages). Opt in via the `agentOsUseProxy` client arg.
'grpc.enable_http_proxy': useHttpProxy ? 1 : 0,
'grpc.max_receive_message_length': 2 ** 30,
'grpc.max_send_message_length': 2 ** 30,
});
Expand Down Expand Up @@ -192,7 +200,7 @@ export class AgentOsClient implements DeviceClient {
this.connectionState = UiControllerClientConnectionState.CONNECTING;
const address = AgentOsClient.normalizeAddress(this.url);
try {
this.client = await AgentOsClient.openChannel(address);
this.client = await AgentOsClient.openChannel(address, this.useHttpProxy);
this.address = address;
await this.startSession();
this.connectionState = UiControllerClientConnectionState.CONNECTED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class UiControlClientDependencyBuilder {
}
return new LegacyAndroidClient(android);
}
return new AgentOsClient(clientArgs.agentOsUrl);
return new AgentOsClient(clientArgs.agentOsUrl, clientArgs.agentOsUseProxy);
}

static async build(clientArgs: ClientArgsWithDefaults): Promise<{
Expand Down Expand Up @@ -102,6 +102,7 @@ export class UiControlClientDependencyBuilder {
return {
...clientArgs,
agentOsUrl: clientArgs.agentOsUrl ?? clientArgs.uiControllerUrl ?? 'localhost:26000',
agentOsUseProxy: clientArgs.agentOsUseProxy ?? false,
aiElementArgs: {
additionalLocations: clientArgs.aiElementArgs?.additionalLocations ?? [],
onLocationNotExist: clientArgs.aiElementArgs?.onLocationNotExist ?? 'error',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export interface ContextArgs {
* to `localhost:23000` to connect to a standalone AgentOS instead.
* @property {string} [uiControllerUrl] - **Deprecated.** Use {@link agentOsUrl} instead. Kept
* for backwards compatibility: used only when `agentOsUrl` is not set.
* @property {boolean} [agentOsUseProxy] - Default: `false`. By default, the gRPC connection to
* the AgentOS is established directly, ignoring proxy environment variables such as
* `grpc_proxy`, `https_proxy` and `http_proxy` (corporate HTTP proxies generally cannot
* tunnel gRPC). Set to `true` to route the connection through the proxy configured in those
* environment variables, e.g., when the AgentOS is only reachable through a proxy.
* @property {string} [inferenceServerUrl] - Default: `'https://inference.askui.com'`.
* Address of the AskUI's inference server which is responsible for understanding the
* screenshots and extracting data from them and returning commands for the UiController.
Expand Down Expand Up @@ -97,6 +102,7 @@ export interface ClientArgs {
* @deprecated Use {@link agentOsUrl} instead. Used only when `agentOsUrl` is not set.
*/
readonly uiControllerUrl?: string
readonly agentOsUseProxy?: boolean
readonly runtime?: Runtime
readonly android?: AndroidArgs
readonly inferenceServerUrl?: string
Expand All @@ -114,6 +120,7 @@ export interface ClientArgs {

export interface ClientArgsWithDefaults extends ClientArgs {
readonly agentOsUrl: string
readonly agentOsUseProxy: boolean
readonly runtime: Runtime
readonly inferenceServerUrl: string
readonly context: Context
Expand Down
Loading