Repository navigation
feat(mobile): a device lease carries agent-device client configuration - #416
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
🟢 e2e web: 11 passedAll 11 tests in 6 files
e2e 0.15.0-canary-20260921154506 · 4.3s · web · run artifacts |
There was a problem hiding this comment.
Devin Review found 2 potential issues.
1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)
| } | ||
|
|
||
| function isJsonValue(value: unknown): boolean { | ||
| if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return true; |
There was a problem hiding this comment.
🟡 Client numbers mutate between processes
When client contains NaN or infinity, isJsonValue accepts it before JSON serialization converts it to null. Warm-up and workers then use different client configuration.
Learn more
JSON has no representation for NaN, Infinity, or -Infinity. JavaScript's JSON.stringify silently emits null for each value instead of rejecting it. The runner-side warm-up uses the original lease object, but child workers reconstruct the binding from serialized JSON. A non-finite client option therefore changes after warm-up.
Example: A provider returns client: { leaseTtlMs: Infinity }. Warm-up creates a client with Infinity; the worker receives { leaseTtlMs: null }.
Recommended fix: Accept numeric values only when Number.isFinite(value) is true, and add coverage for all three non-finite values.
| if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return true; | |
| if (value === null || typeof value === 'string' || (typeof value === 'number' && Number.isFinite(value)) || typeof value === 'boolean') return true; |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Fixed in 8b71786: isJsonValue accepts a number only when Number.isFinite holds, and the refusal test covers NaN and both infinities.
| * worker through the environment; `session`, `daemonBaseUrl`, and | ||
| * `daemonAuthToken` are not part of it. | ||
| */ | ||
| export type DeviceClientConfig = Omit<AgentDeviceClientConfig, 'session' | 'daemonBaseUrl' | 'daemonAuthToken'>; |
There was a problem hiding this comment.
🟡 Typed transports always fail leasing
DeviceClientConfig includes the function-valued daemonTransport, but isClientConfig rejects every function. Providers using this exported option typecheck, then every lease fails during prepare.
| export type DeviceClientConfig = Omit<AgentDeviceClientConfig, 'session' | 'daemonBaseUrl' | 'daemonAuthToken'>; | |
| export type DeviceClientConfig = Omit<AgentDeviceClientConfig, 'session' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport'>; |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
In agent-device 0.21.6 daemonTransport is a string preference (auto | socket | http), not a function, so a typed value would have leased fine. It is still not a device fact but how the worker reaches its daemon, so 8b71786 drops it from DeviceClientConfig and refuses it at prepare like the other reserved keys.
🟢 e2e web agent: 21 passed, 3 skipped22 agent steps · 83 model calls · 294.9k tokens (83% cached) · $0.0426 All 24 tests in 4 files
e2e 0.15.0-canary-20260921154506 · 3m 29s · web · run artifacts |
… client configuration
A
DeviceLeasecan now carryclient: agent-device client configuration the worker's client is created with, next to thedaemonaddress, which becomes optional.tenant,runId,leaseId,leaseBackend,leaseProvider, asleases.allocatereturned it. A command without that scope falls back to the local inventory, and on a Mac with a booted simulator the test silently runs there while the hosted instance sits idle.leases.allocategave it.client.stateDirreaches a daemon the provider started for the run, so such a provider needs nodaemonaddress at all. A lease namesdaemon,client, or both.clientis JSON data, since it travels to the worker through the environment under the existing 16 KiB cap.session,daemonBaseUrl, anddaemonAuthTokenstay with the engine anddaemon; a lease setting them is refused atprepare.DeviceClientConfigandDeviceConnectionare exported. The mobile guide gains a second example, a provider on a device cloud through agent-device, typechecked like the first.flowchart LR P[provider.acquire] -->|lease.client| B[SlotBinding in worker env] B --> F["createAgentDeviceClient({ ...client, session, daemonBaseUrl?, daemonAuthToken? })"] F --> D[daemon] D -->|lease scope on every command| H[hosted device]Refs:
packages/mobile/src/bindings.ts(DeviceClientConfig,isSlotBinding),packages/mobile/src/provider.ts(DeviceLease,isDeviceLease),packages/mobile/src/engine.ts(the client factory),docs/examples/mobile/device-cloud-provider.ts.