From 3654a84e1b51439054d3709a699c4ec63a58076c Mon Sep 17 00:00:00 2001 From: artin Date: Thu, 3 Sep 2026 18:10:24 +0800 Subject: [PATCH 1/9] feat(remote): add HarmonyOS proxy lease backend Signed-off-by: Ark --- packages/kernel/src/contracts.ts | 4 ++-- src/cli/commands/connection-runtime.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/kernel/src/contracts.ts b/packages/kernel/src/contracts.ts index a42a4154b..0c569035a 100644 --- a/packages/kernel/src/contracts.ts +++ b/packages/kernel/src/contracts.ts @@ -5,7 +5,7 @@ export { defaultHintForCode, normalizeError } from './errors.ts'; import type { PlatformSelector } from './device.ts'; export type SessionRuntimeHints = { - platform?: 'ios' | 'android'; + platform?: 'ios' | 'android' | 'harmonyos'; metroHost?: string; metroPort?: number; bundleUrl?: string; @@ -44,7 +44,7 @@ export type LocalInstallSource = Extract Date: Thu, 3 Sep 2026 18:17:44 +0800 Subject: [PATCH 2/9] feat(remote): add HarmonyOS proxy lease backend Signed-off-by: Ark --- src/cli/commands/connection-runtime.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cli/commands/connection-runtime.ts b/src/cli/commands/connection-runtime.ts index 1a9274d62..228d135c4 100644 --- a/src/cli/commands/connection-runtime.ts +++ b/src/cli/commands/connection-runtime.ts @@ -689,6 +689,7 @@ export function resolveRequestedLeaseBackend(flags: CliFlags): LeaseBackend | un if (flags.leaseBackend) return flags.leaseBackend; if (flags.platform === 'android') return 'android-instance'; if (flags.platform === 'ios') return 'ios-instance'; + if (flags.platform === 'harmonyos') return 'harmonyos-instance'; return undefined; } @@ -697,7 +698,7 @@ function requireRequestedLeaseBackend(flags: CliFlags, command: string): LeaseBa if (leaseBackend) return leaseBackend; throw new AppError( 'INVALID_ARGS', - `${command} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`, + `${command} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`, ); } From 390e276989cc6d982c8acc73aa83d1092d61b902 Mon Sep 17 00:00:00 2001 From: artin Date: Thu, 3 Sep 2026 20:14:59 +0800 Subject: [PATCH 3/9] feat(remote): complete HarmonyOS lease backend wiring Signed-off-by: Ark --- src/__tests__/remote-connection.test.ts | 6 ++++++ src/cli/commands/connection-runtime.ts | 2 +- src/commands/cli-grammar/flag-definitions-connection.ts | 4 ++-- src/remote/remote-config-schema.ts | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/__tests__/remote-connection.test.ts b/src/__tests__/remote-connection.test.ts index c97a819e4..58486f992 100644 --- a/src/__tests__/remote-connection.test.ts +++ b/src/__tests__/remote-connection.test.ts @@ -34,7 +34,9 @@ import { materializeRemoteConnectionForCommand, CLOUD_WEBDRIVER_REMOTE_LEASE_TTL_MS, PROXY_REMOTE_LEASE_TTL_MS, + resolveRequestedLeaseBackend, } from '../cli/commands/connection-runtime.ts'; + import { stopMetroCompanion } from '../metro/client-metro-companion.ts'; import { AppError } from '@agent-device/kernel/errors'; import { @@ -45,6 +47,10 @@ import { } from '../remote/remote-connection-state.ts'; import type { AgentDeviceClient } from '../agent-device-client.ts'; +test('HarmonyOS platform resolves to its proxy lease backend', () => { + assert.equal(resolveRequestedLeaseBackend({ platform: 'harmonyos' } as never), 'harmonyos-instance'); +}); + afterEach(() => { vi.clearAllMocks(); vi.restoreAllMocks(); diff --git a/src/cli/commands/connection-runtime.ts b/src/cli/commands/connection-runtime.ts index 228d135c4..7d2b0e1b6 100644 --- a/src/cli/commands/connection-runtime.ts +++ b/src/cli/commands/connection-runtime.ts @@ -734,7 +734,7 @@ function isRuntimeCompatibleWithPlatform( runtime: SessionRuntimeHints, platform: CliFlags['platform'], ): boolean { - if (!runtime.platform || !platform || (platform !== 'ios' && platform !== 'android')) { + if (!runtime.platform || !platform) { return true; } return runtime.platform === platform; diff --git a/src/commands/cli-grammar/flag-definitions-connection.ts b/src/commands/cli-grammar/flag-definitions-connection.ts index c59893b4f..d2ab5cfd6 100644 --- a/src/commands/cli-grammar/flag-definitions-connection.ts +++ b/src/commands/cli-grammar/flag-definitions-connection.ts @@ -105,8 +105,8 @@ export const CONNECTION_FLAG_DEFINITIONS: readonly FlagDefinition[] = [ key: 'leaseBackend', names: ['--lease-backend'], type: 'enum', - enumValues: ['ios-simulator', 'ios-instance', 'android-instance'], - usageLabel: '--lease-backend ios-simulator|ios-instance|android-instance', + enumValues: ['ios-simulator', 'ios-instance', 'android-instance', 'harmonyos-instance'], + usageLabel: '--lease-backend ios-simulator|ios-instance|android-instance|harmonyos-instance', usageDescription: 'Lease backend for remote tenant connection admission', }, { diff --git a/src/remote/remote-config-schema.ts b/src/remote/remote-config-schema.ts index 6c33f206d..f3cfc2752 100644 --- a/src/remote/remote-config-schema.ts +++ b/src/remote/remote-config-schema.ts @@ -61,7 +61,7 @@ export const REMOTE_CONFIG_FIELD_SPECS = [ { key: 'leaseBackend', type: 'enum', - enumValues: ['ios-simulator', 'ios-instance', 'android-instance'], + enumValues: ['ios-simulator', 'ios-instance', 'android-instance', 'harmonyos-instance'], }, { key: 'platform', type: 'enum', enumValues: PLATFORM_SELECTORS }, { key: 'target', type: 'enum', enumValues: ['mobile', 'tv', 'desktop'] }, From fb8a1d2a7d5899ae3d5d85960ef3f331b1460c8b Mon Sep 17 00:00:00 2001 From: artin Date: Thu, 3 Sep 2026 20:20:16 +0800 Subject: [PATCH 4/9] feat(remote): complete HarmonyOS lease backend wiring Signed-off-by: Ark --- CHANGELOG.md | 6 +++--- src/daemon/__tests__/lease-registry.test.ts | 5 +++++ src/daemon/lease-registry-scope.ts | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb125d153..723b1393e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,9 @@ ## Unreleased -- Added strict `wait absent [timeoutMs]` polling for zero selector matches. Incomplete, - sparse, truncated, scoped, depth-limited, and Android unreadable captures cannot prove absence; - deadline diagnostics retain typed capture evidence and stable first-match details (#2236). +- Added the `harmonyos-instance` remote lease backend so HarmonyOS proxy devices can participate in + the same explicit allocation, heartbeat, and close lifecycle as other remote instances (#2266). + - Fixed: `settings airplane on|off` now takes an Android device offline. It is applied through the connectivity service (`cmd connectivity airplane-mode`), which drives the radios, instead of writing `airplane_mode_on` and broadcasting `ACTION_AIRPLANE_MODE_CHANGED` — a broadcast Android diff --git a/src/daemon/__tests__/lease-registry.test.ts b/src/daemon/__tests__/lease-registry.test.ts index 61dbffbe6..fe3e6c814 100644 --- a/src/daemon/__tests__/lease-registry.test.ts +++ b/src/daemon/__tests__/lease-registry.test.ts @@ -2,6 +2,7 @@ import { test } from 'vitest'; import assert from 'node:assert/strict'; import { createRequestCanceledError } from '@agent-device/kernel/errors'; import { LeaseRegistry } from '../lease-registry.ts'; +import { normalizeLeaseBackend } from '../lease-registry-scope.ts'; import { HUMAN_CONTROL_LEASE_REQUEST, HUMAN_CONTROL_SCOPE, @@ -9,6 +10,10 @@ import { createControlLatch, } from './human-control-fixtures.ts'; +test('normalizeLeaseBackend accepts HarmonyOS instance backend', () => { + assert.equal(normalizeLeaseBackend('harmonyos-instance'), 'harmonyos-instance'); +}); + test('allocateLease creates lease and enforces tenant/run validation', () => { const registry = new LeaseRegistry(); const lease = registry.allocateLease({ diff --git a/src/daemon/lease-registry-scope.ts b/src/daemon/lease-registry-scope.ts index 614afd244..f3d6ca59e 100644 --- a/src/daemon/lease-registry-scope.ts +++ b/src/daemon/lease-registry-scope.ts @@ -133,7 +133,7 @@ export function normalizeRequiredLeaseId(raw: string | undefined): string { export function normalizeLeaseBackend(raw: string | undefined): LeaseBackend { const value = (raw ?? '').trim().toLowerCase(); if (!value || value === 'ios-simulator') return 'ios-simulator'; - if (value === 'ios-instance' || value === 'android-instance') return value; + if (value === 'ios-instance' || value === 'android-instance' || value === 'harmonyos-instance') return value; throw new AppError('INVALID_ARGS', `Unsupported lease backend: ${raw ?? ''}`); } From 1533c527e419d4810f3ddb79e8cb35920505d5ab Mon Sep 17 00:00:00 2001 From: artin Date: Thu, 3 Sep 2026 20:24:29 +0800 Subject: [PATCH 5/9] fix(remote): accept Harmony runtime hints Signed-off-by: Ark --- packages/kernel/src/contracts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kernel/src/contracts.ts b/packages/kernel/src/contracts.ts index 0c569035a..a42ee3462 100644 --- a/packages/kernel/src/contracts.ts +++ b/packages/kernel/src/contracts.ts @@ -271,7 +271,7 @@ function optionalEnum( export const daemonRuntimeSchema = schema((input, path) => { const record = expectObject(input, path); return { - platform: optionalEnum(record, 'platform', ['ios', 'android'] as const, path), + platform: optionalEnum(record, 'platform', ['ios', 'android', 'harmonyos'] as const, path), metroHost: optionalString(record, 'metroHost', path), metroPort: optionalInteger(record, 'metroPort', path), bundleUrl: optionalString(record, 'bundleUrl', path), From c496a27c38effa921db3d768e7b40fa9b45aa550 Mon Sep 17 00:00:00 2001 From: artin Date: Thu, 3 Sep 2026 21:02:46 +0800 Subject: [PATCH 6/9] fix(remote): complete Harmony runtime lease plumbing Signed-off-by: Ark --- CHANGELOG.md | 5 +++-- src/cli/commands/connection-runtime.ts | 6 +++++- src/daemon/session-runtime.ts | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 723b1393e..40c17e935 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,9 @@ ## Unreleased -- Added the `harmonyos-instance` remote lease backend so HarmonyOS proxy devices can participate in - the same explicit allocation, heartbeat, and close lifecycle as other remote instances (#2266). +- Added the `harmonyos-instance` lease contract and CLI/runtime plumbing as a prerequisite for + HarmonyOS proxy support; provider/daemon allocation remains gated until its end-to-end lifecycle + is implemented and validated (#2266). - Fixed: `settings airplane on|off` now takes an Android device offline. It is applied through the connectivity service (`cmd connectivity airplane-mode`), which drives the radios, instead of diff --git a/src/cli/commands/connection-runtime.ts b/src/cli/commands/connection-runtime.ts index 7d2b0e1b6..871aabd06 100644 --- a/src/cli/commands/connection-runtime.ts +++ b/src/cli/commands/connection-runtime.ts @@ -734,7 +734,11 @@ function isRuntimeCompatibleWithPlatform( runtime: SessionRuntimeHints, platform: CliFlags['platform'], ): boolean { - if (!runtime.platform || !platform) { + if ( + !runtime.platform || + !platform || + (platform !== 'ios' && platform !== 'android' && platform !== 'harmonyos') + ) { return true; } return runtime.platform === platform; diff --git a/src/daemon/session-runtime.ts b/src/daemon/session-runtime.ts index 52b68b84a..07f84be7b 100644 --- a/src/daemon/session-runtime.ts +++ b/src/daemon/session-runtime.ts @@ -86,10 +86,10 @@ function normalizeRuntimePlatformInput( platform?: RuntimePlatform, ): RuntimePlatform | undefined { if (value === undefined) return platform; - if (value !== 'ios' && value !== 'android') { + if (value !== 'ios' && value !== 'android' && value !== 'harmonyos') { throw new AppError( 'INVALID_ARGS', - `Invalid open runtime platform: ${String(value)}. Use "ios" or "android".`, + `Invalid open runtime platform: ${String(value)}. Use "ios", "android", or "harmonyos".`, ); } if (platform && value !== platform) { @@ -104,7 +104,7 @@ function normalizeRuntimePlatformInput( export function toRuntimePlatform( platform: CommandFlags['platform'] | DeviceInfo['platform'] | 'apple' | undefined, ): RuntimePlatform | undefined { - if (platform === 'ios' || platform === 'android') { + if (platform === 'ios' || platform === 'android' || platform === 'harmonyos') { return platform; } return undefined; From 88883e8986ecce1d71c0aed25488d99024048090 Mon Sep 17 00:00:00 2001 From: artin Date: Thu, 3 Sep 2026 21:14:39 +0800 Subject: [PATCH 7/9] test(wire): acknowledge Harmony lease additions Signed-off-by: Ark --- test/wire-compat/ledger.json | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/test/wire-compat/ledger.json b/test/wire-compat/ledger.json index 7667d5a13..dc53b63f9 100644 --- a/test/wire-compat/ledger.json +++ b/test/wire-compat/ledger.json @@ -18,16 +18,16 @@ "packages/kernel/src/contracts.ts#DaemonResponseData": "sha256:f16e61b7f0ea8cdae82349508383af2f97a4c16c8aa21952d833094673f86afc", "packages/kernel/src/contracts.ts#JsonRpcId": "sha256:5a5fdff1cd85971214117d69a8278d0ecaf21a6fa3f4582155d9b3d9cad1fbd0", "packages/kernel/src/contracts.ts#JsonRpcRequestEnvelope": "sha256:d6328309fc4f8b310b88680181e46c802329de9b0e45682dd2e0f0c3e8d090e4", - "packages/kernel/src/contracts.ts#LEASE_BACKENDS": "sha256:9fb296dcfd56556e4dd020bcb40f3b70890b274600e634aa2c380d860b38c022", + "packages/kernel/src/contracts.ts#LEASE_BACKENDS": "sha256:6bec996666d1043a8d23e60d5b1e50ef9341909a02f19060a3132bb72dcc3155", "packages/kernel/src/contracts.ts#LeaseBackend": "sha256:dce397343cda82ce4e3e43b534b1f642cd37568ed304f4783caddc3524c1cae5", "packages/kernel/src/contracts.ts#RESPONSE_LEVELS": "sha256:cef29c3b56c299e35a7fee8058b90dc4a6f65a46a420e4f11f77c8ca7d0359c8", "packages/kernel/src/contracts.ts#ResponseCost": "sha256:2a44de54e8b5c886b36da1500e22d634ec7e12961d2c93b689d2b1aa8c15f186", "packages/kernel/src/contracts.ts#ResponseLevel": "sha256:c7329d28e745b5e69b86aa1a686befa314b98248afbe5e0e2d7d395f0d777f9b", "packages/kernel/src/contracts.ts#SESSION_ISOLATION_MODES": "sha256:3d4b3048e22bb0ceccc98cf8fd93a87a1a1e2dad96fa03cffff6d0ecedb58689", "packages/kernel/src/contracts.ts#SessionIsolationMode": "sha256:beea941fe57b000902da28af15a27aa18d0c957408209e3ec372fcf7f605fa7c", - "packages/kernel/src/contracts.ts#SessionRuntimeHints": "sha256:6b945688ad5ab68370ec001d962974e1397c39d47c6f7ca2a65b03f5ccdd91c6", + "packages/kernel/src/contracts.ts#SessionRuntimeHints": "sha256:7e055a99bc6adbb3efc37b0691055f5370f35f8b96ae6af73295ccce61e05dfe", "packages/kernel/src/contracts.ts#commandRpcParamsSchema": "sha256:d0ce05c236ce5b0b52631ab7b8a75d38859fbfba58cfb28dd3f9d84f2dba2c1f", - "packages/kernel/src/contracts.ts#daemonRuntimeSchema": "sha256:010c171164ce9516e1c1b00e89e698a11842ff9c3bac3f2e8e3814de7c8be78c", + "packages/kernel/src/contracts.ts#daemonRuntimeSchema": "sha256:859eabaf6679d117feb2b4873b6ac69731cc06989645080817d39c43a24deea5", "packages/kernel/src/contracts.ts#jsonRpcRequestSchema": "sha256:67e6b8a28b39a3883424a565ae7033c336dc2ea6b193e9b32bb98eb3e18dca7c", "packages/kernel/src/device.ts#PLATFORM_SELECTORS": "sha256:36e9da1cc660c0ddfb4cf52521f7f230341ff20e3ebda3405ba7c1799476c42d", "packages/kernel/src/device.ts#PlatformSelector": "sha256:61de3f003507ea2f53b396b0146c17670bf674a2db2132e19c462ca6c10cc8fd", @@ -227,6 +227,21 @@ "declaration": "src/daemon/client/daemon-client-rpc.ts#appErrorFromDaemonError", "digest": "sha256:ac4761006c71d93ccba9f8e37cbd4cf48283dbb22737c163dc9c1a878e154eea", "rationale": "#1862 client-side only: this rehydrates the new optional structured `cause` when present. Released daemons that omit it follow the unchanged path, and no request field or existing response field is narrowed." + }, + { + "declaration": "packages/kernel/src/contracts.ts#LEASE_BACKENDS", + "digest": "sha256:6bec996666d1043a8d23e60d5b1e50ef9341909a02f19060a3132bb72dcc3155", + "rationale": "#2266 adds the additive harmonyos-instance lease backend literal. Protocol-2 peers ignore the new backend unless explicitly requested; existing iOS/Android values and payloads remain unchanged." + }, + { + "declaration": "packages/kernel/src/contracts.ts#SessionRuntimeHints", + "digest": "sha256:7e055a99bc6adbb3efc37b0691055f5370f35f8b96ae6af73295ccce61e05dfe", + "rationale": "#2266 adds the optional HarmonyOS platform value to runtime hints. Existing iOS/Android hints retain their shape and released peers can ignore the additive value." + }, + { + "declaration": "packages/kernel/src/contracts.ts#daemonRuntimeSchema", + "digest": "sha256:859eabaf6679d117feb2b4873b6ac69731cc06989645080817d39c43a24deea5", + "rationale": "#2266 broadens runtime-hint validation to accept the additive HarmonyOS platform value; existing protocol-2 runtime hints remain valid and unchanged." } ] } From 6c537091d699898f6b653dca8d7c784738295ef9 Mon Sep 17 00:00:00 2001 From: artin Date: Thu, 3 Sep 2026 21:46:33 +0800 Subject: [PATCH 8/9] test(remote): close HarmonyOS lease review gaps Signed-off-by: Ark --- CHANGELOG.md | 3 +++ src/__tests__/remote-connection.test.ts | 7 ++++++- src/daemon/__tests__/lease-registry-scope.test.ts | 5 +++++ src/daemon/__tests__/lease-registry.test.ts | 5 ----- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40c17e935..42e8e687f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +- Added strict `wait absent [timeoutMs]` polling for zero selector matches. Incomplete, + sparse, truncated, scoped, depth-limited, and Android unreadable captures cannot prove absence; + deadline diagnostics retain typed capture evidence and stable first-match details (#2236). - Added the `harmonyos-instance` lease contract and CLI/runtime plumbing as a prerequisite for HarmonyOS proxy support; provider/daemon allocation remains gated until its end-to-end lifecycle is implemented and validated (#2266). diff --git a/src/__tests__/remote-connection.test.ts b/src/__tests__/remote-connection.test.ts index 58486f992..216999ddf 100644 --- a/src/__tests__/remote-connection.test.ts +++ b/src/__tests__/remote-connection.test.ts @@ -48,7 +48,12 @@ import { import type { AgentDeviceClient } from '../agent-device-client.ts'; test('HarmonyOS platform resolves to its proxy lease backend', () => { - assert.equal(resolveRequestedLeaseBackend({ platform: 'harmonyos' } as never), 'harmonyos-instance'); + assert.equal( + resolveRequestedLeaseBackend( + forceConnectFlags({ stateDir: '/tmp/agent-device', remoteConfig: '/tmp/remote.json', platform: 'harmonyos' }), + ), + 'harmonyos-instance', + ); }); afterEach(() => { diff --git a/src/daemon/__tests__/lease-registry-scope.test.ts b/src/daemon/__tests__/lease-registry-scope.test.ts index 1bb76af55..e89f0fc41 100644 --- a/src/daemon/__tests__/lease-registry-scope.test.ts +++ b/src/daemon/__tests__/lease-registry-scope.test.ts @@ -4,9 +4,14 @@ import { createLeaseTtlResolver, leaseDeviceBindingKey, normalizeAllocateLeaseRequest, + normalizeLeaseBackend, } from '../lease-registry-scope.ts'; import { HUMAN_CONTROL_LEASE_REQUEST, HUMAN_CONTROL_SCOPE } from './human-control-fixtures.ts'; +test('normalizeLeaseBackend accepts HarmonyOS instance backend', () => { + assert.equal(normalizeLeaseBackend('harmonyos-instance'), 'harmonyos-instance'); +}); + test('allocation and human control share the exact contention identity', () => { const scope = normalizeAllocateLeaseRequest(HUMAN_CONTROL_LEASE_REQUEST); assert.equal(leaseDeviceBindingKey(scope), leaseDeviceBindingKey(HUMAN_CONTROL_SCOPE)); diff --git a/src/daemon/__tests__/lease-registry.test.ts b/src/daemon/__tests__/lease-registry.test.ts index fe3e6c814..61dbffbe6 100644 --- a/src/daemon/__tests__/lease-registry.test.ts +++ b/src/daemon/__tests__/lease-registry.test.ts @@ -2,7 +2,6 @@ import { test } from 'vitest'; import assert from 'node:assert/strict'; import { createRequestCanceledError } from '@agent-device/kernel/errors'; import { LeaseRegistry } from '../lease-registry.ts'; -import { normalizeLeaseBackend } from '../lease-registry-scope.ts'; import { HUMAN_CONTROL_LEASE_REQUEST, HUMAN_CONTROL_SCOPE, @@ -10,10 +9,6 @@ import { createControlLatch, } from './human-control-fixtures.ts'; -test('normalizeLeaseBackend accepts HarmonyOS instance backend', () => { - assert.equal(normalizeLeaseBackend('harmonyos-instance'), 'harmonyos-instance'); -}); - test('allocateLease creates lease and enforces tenant/run validation', () => { const registry = new LeaseRegistry(); const lease = registry.allocateLease({ From 68c21a069e235b2f0333b709eb6b37a14a9becec Mon Sep 17 00:00:00 2001 From: artin Date: Thu, 3 Sep 2026 21:53:47 +0800 Subject: [PATCH 9/9] fix(runtime): update HarmonyOS support error text Signed-off-by: Ark --- src/daemon/session-runtime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/daemon/session-runtime.ts b/src/daemon/session-runtime.ts index 07f84be7b..aaaf2dbf5 100644 --- a/src/daemon/session-runtime.ts +++ b/src/daemon/session-runtime.ts @@ -215,7 +215,7 @@ function resolveSessionRuntimeHints( if (runtime.platform && device && !deviceRuntimePlatform) { throw new AppError( 'INVALID_ARGS', - `Session runtime hints are only supported on iOS and Android sessions, but session "${sessionName}" is bound to ${boundPlatform}.`, + `Session runtime hints are only supported on iOS, Android, and HarmonyOS sessions, but session "${sessionName}" is bound to ${boundPlatform}.`, ); } if (runtime.platform && deviceRuntimePlatform && runtime.platform !== deviceRuntimePlatform) {