@agimon-ai/po-ios 0.0.1-alpha.0 → 0.0.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +12 -4
  2. package/dist/{contracts-C54pSczx.cjs → contracts-BsO_lEi8.cjs} +16 -1
  3. package/dist/contracts-BsO_lEi8.cjs.map +1 -0
  4. package/dist/{contracts-D41ZfB5m.mjs → contracts-DH0gdDYT.mjs} +5 -2
  5. package/dist/contracts-DH0gdDYT.mjs.map +1 -0
  6. package/dist/extensions/server.cjs +841 -251
  7. package/dist/extensions/server.cjs.map +1 -1
  8. package/dist/extensions/server.d.mts.map +1 -1
  9. package/dist/extensions/server.mjs +844 -254
  10. package/dist/extensions/server.mjs.map +1 -1
  11. package/dist/index.cjs +1 -1
  12. package/dist/index.d.mts +38 -9
  13. package/dist/index.d.mts.map +1 -1
  14. package/dist/index.mjs +1 -1
  15. package/native/device-runner/PoRunner.xcodeproj/project.pbxproj +204 -0
  16. package/native/device-runner/PoRunner.xcodeproj/xcshareddata/xcschemes/PoRunner.xcscheme +20 -0
  17. package/native/device-runner/PoRunnerUITests/Runner.swift +231 -0
  18. package/native/sim-helper/PRIVATE_APIS.md +98 -16
  19. package/native/sim-helper/Sources/PoIosCore/Compaction.swift +8 -0
  20. package/native/sim-helper/Sources/PoIosCore/Protocol.swift +48 -0
  21. package/native/sim-helper/Sources/PoIosSimHelper/Backends.swift +296 -46
  22. package/native/sim-helper/Sources/PoIosSimHelper/PrivateApis.swift +133 -7
  23. package/native/sim-helper/Sources/PoIosSimHelper/main.swift +3 -1
  24. package/native/sim-helper/Tests/PoIosCoreTests/CompactionTests.swift +2 -1
  25. package/native/sim-helper/Tests/PoIosCoreTests/ProtocolTests.swift +17 -0
  26. package/package.json +13 -7
  27. package/src/prompts/codemode-how-to-ios/SKILL.md +15 -6
  28. package/dist/contracts-C54pSczx.cjs.map +0 -1
  29. package/dist/contracts-D41ZfB5m.mjs.map +0 -1
package/README.md CHANGED
@@ -11,7 +11,7 @@ This package is a composable [Po](https://www.npmjs.com/package/@agimon-ai/po) s
11
11
 
12
12
  ## Install
13
13
 
14
- The layer is opt-in: select the `ios` layer in your Po modes. The package declares poServer metadata for native server discovery.
14
+ The package is opt-in and intentionally absent from init templates. Define an `ios` layer with `packages: ['@agimon-ai/po-ios']` in your modes file, then select that layer in a major mode. The package declares poServer metadata for native server discovery.
15
15
 
16
16
  ## Use
17
17
 
@@ -27,7 +27,7 @@ await ios.release();
27
27
 
28
28
  ## Package behavior
29
29
 
30
- One pool serves every Po server on the machine. Pool state lives in the shared `po/db` (`ios_*` tables); simulators live in Po's own device set at `<po home>/ios/devices`, never in the person's default set. Size it in `~/.po/config.yaml` (global only, read once per server):
30
+ Each server elects one global pool owner, including when a workspace selects the iOS layer. Servers using the same Po home share pool state through `po/db` (`ios_*` tables); simulators live at `<po home>/ios/devices`, never in the person's default set. Size it in `<po home>/config.yaml` (global only, read once per activation):
31
31
 
32
32
  ```yaml
33
33
  ios:
@@ -41,9 +41,17 @@ ios:
41
41
 
42
42
  Release uninstalls the apps a session installed and keeps the device warm. Devices of a dead server are erased before reuse.
43
43
 
44
- Accessibility and touch (`observe`, `tap`, `type`, `swipe`, `pressButton`, `waitFor`, `settle`) go through a resident Swift helper in `native/sim-helper`. The server builds it on first use with the person's Xcode (`xcrun swift build`) into `<po home>/ios/native/<hash>/`; set `ios.helperPath` to use a prebuilt one instead. Its private framework calls are not recorded yet (see `native/sim-helper/PRIVATE_APIS.md`), so until then those calls return `IOS_HELPER_UNAVAILABLE`.
44
+ Accessibility and touch (`observe`, `tap`, `type`, `swipe`, `pressButton`, `waitFor`, `settle`) go through a resident Swift helper in `native/sim-helper`. The server builds it on first use with the person's Xcode (`xcrun swift build`) into `<po home>/ios/native/<hash>/`; set `ios.helperPath` to use a prebuilt one instead. On Xcode 27.1 (27A9275) and iOS 26.5, direct native-protocol trials verified observation, taps, timed swipes, US-layout ASCII typing (including shifted punctuation and return), home and lock. Arbitrary Unicode text, touches on a landscape app interface and Siri/volume buttons explicitly return `IOS_HELPER_UNAVAILABLE`, with no clipboard or AX-value fallback. Unsupported text is rejected before any keys are emitted. Missing or changed private API shapes also fail explicitly. See `native/sim-helper/PRIVATE_APIS.md` for evidence and limits.
45
45
 
46
- Physical devices: `ios.devices()` lists what CoreDevice sees (`xcrun devicectl list devices`), and `ios.acquireDevice({ udid })` leases a paired, connected phone after the person approves it. A phone lease shares the `ios_lease` table (`kind = 'device'`) so two sessions never hold one phone, but it has no `ios_device` row: the pool never boots, erases or counts it against `maxBooted`. On a phone only `install` (a device-signed `.app`), `uninstall`, `launch` and `release` work; release only drops the lease. Accessibility, screenshots and logs on phones need the XCUITest runner, which is not built yet.
46
+ This is a partial implementation, not completion of the full iOS plan. Built-layer trials verified the supported simulator workflow, stale refs, fail-closed Unicode rejection, release/warm reuse, crash reclaim and unchanged helper-binary cache reuse. Three immediate release/reinstall/launch cycles passed after fixing zero-frame window readiness. Separate native trials verified A-only tap/text and B-only taps across two portrait simulators. Observation follows an app's landscape interface, but no tested touch mapping reached it, so landscape taps and swipes are refused. The child borrowed-lease check remains unverified; the inline child reported no `exec` tool. Input acknowledgment is not UI completion: use `waitFor` after actions. A lock transition took about three seconds to appear in AX observations.
47
+
48
+ Physical devices: `ios.devices()` lists what CoreDevice sees (`xcrun devicectl list devices`), and `ios.acquireDevice({ udid })` leases a paired, reachable phone after the person approves it. An idle disconnected tunnel is checked with a bounded device-info request rather than rejected solely by its listed state. A phone lease shares the `ios_lease` table (`kind = 'device'`) so two sessions never hold one phone, but it has no `ios_device` row: the pool never boots, erases or counts it against `maxBooted`. Signed app install, uninstall, launch and console logs work without a runner. Phone `logs` is partial: `launch` keeps `devicectl device process launch --console` attached and buffers the app's stdout, stderr and NSLog lines (last 5000, 12 hours at most), because `log collect --device-udid` requires root. The unified system log, `process` and `subsystem` are not available on a phone.
49
+
50
+ For phone accessibility and input, set `ios.device.developmentTeam` in the admitted global config and connect the phone by USB. First use builds and installs Po's own signed XCUITest runner with automatic provisioning. It binds only a USB IPv4 link-local address (`169.254.*`), requires a random per-run token and reuses the helper protocol. No WDA, Appium or iproxy is used. Observation selects a foreground app launched under this lease, otherwise SpringBoard. Release stops the runner and uninstalls its test host before freeing the lease, leaving the person's other apps installed. Cleanup failure holds the lease and can be retried. Phone screenshots, terminate and openUrl remain unavailable through `ios`; home, lock and Siri fail explicitly. Volume and rotation are unverified. An explicit bottom-edge swipe can leave an app.
51
+
52
+ Live phone evidence (iPhone 15 Pro, iOS 26.6.2, Xcode 27.1): listing by CoreDevice identifier and UDID, a wildcard development-profile build installed, launched and uninstalled, and `createDeviceCtl` console capture returned the sample app's stderr, stdout, NSLog and tick lines, then nothing after `forgetConsole`. Separate native runner trials verified probe, observation, tap, swipe and focused typing over USB. Home acknowledged without navigation, so it is now refused. A direct `devicectl` screenshot confirmed the typed text without submitting it; this does not establish `ios.screenshot` support. The probe runner was uninstalled. Automated service tests cover signing gates, protocol/authentication, cancellation and retryable cleanup. The first built-layer phone run acquired and installed successfully, then timed out waiting for launch status; separate uninstall/release cleanup succeeded. Its repeated acceptance is pending after the fix below.
53
+
54
+ Automatic startup passed after the phone was unlocked: signed build/start, token handshake, a 53-element observation, explicit home refusal and runner cleanup completed in about 12 seconds. A real injected-platform-shell trial then exposed buffered `devicectl` status output: app logs streamed, but `launch` waited until timeout for its success line. Console launches now set `NSUnbufferedIO=YES`. The same platform-shell pipeline passed install, runner startup, launch, tap/count change, exact typed text, secure-value exclusion, visible-row swipe changes, app console and cleanup in about 19 seconds. The built-layer phone check is separate. Keep the phone unlocked and awake during startup.
47
55
 
48
56
  ## Help
49
57
 
@@ -18,6 +18,9 @@ const SIMCTL_TIMEOUT_MS = 12e4;
18
18
  const BOOT_TIMEOUT_MS = 3e5;
19
19
  const MAX_COMMAND_OUTPUT_CHARS = 8388608;
20
20
  const SCREENSHOT_MAX_PIXELS = 1200;
21
+ /** A phone app's console: lines kept per device, and how long devicectl stays attached before it is stopped. */
22
+ const CONSOLE_MAX_LINES = 5e3;
23
+ const CONSOLE_MAX_MS = 432e5;
21
24
  /** Fixed tool path: never the server's own PATH. */
22
25
  const IOS_TOOL_PATH = "/usr/bin:/bin:/usr/sbin:/sbin";
23
26
  const IOS_ERROR_CODES = [
@@ -68,6 +71,18 @@ Object.defineProperty(exports, "BOOT_TIMEOUT_MS", {
68
71
  return BOOT_TIMEOUT_MS;
69
72
  }
70
73
  });
74
+ Object.defineProperty(exports, "CONSOLE_MAX_LINES", {
75
+ enumerable: true,
76
+ get: function() {
77
+ return CONSOLE_MAX_LINES;
78
+ }
79
+ });
80
+ Object.defineProperty(exports, "CONSOLE_MAX_MS", {
81
+ enumerable: true,
82
+ get: function() {
83
+ return CONSOLE_MAX_MS;
84
+ }
85
+ });
71
86
  Object.defineProperty(exports, "HELPER_BUILD_LOCK", {
72
87
  enumerable: true,
73
88
  get: function() {
@@ -219,4 +234,4 @@ Object.defineProperty(exports, "WAIT_MAX_POLL_MS", {
219
234
  }
220
235
  });
221
236
 
222
- //# sourceMappingURL=contracts-C54pSczx.cjs.map
237
+ //# sourceMappingURL=contracts-BsO_lEi8.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts-BsO_lEi8.cjs","names":["defineServiceContract"],"sources":["../src/constants/ios.ts","../src/schemas/contracts.ts"],"sourcesContent":["export const IOS_NAMESPACE = 'ios';\nexport const IOS_PACKAGE = '@agimon-ai/po-ios';\nexport const IOS_POOL_SERVICE = 'po/ios-pool';\n\n/** Table prefix in the shared `po/db`. */\nexport const IOS_DB_PREFIX = 'ios';\n/** `<po home>/ios/devices` is the simulator device set Po owns; the person's own simulators live elsewhere. */\nexport const IOS_DIRECTORY = 'ios';\nexport const IOS_DEVICE_SET_DIRECTORY = 'devices';\nexport const IOS_DEVICE_NAME_PREFIX = 'po-pool-';\n\nexport const IOS_POOL_DEFAULTS = {\n minBooted: 0,\n maxBooted: 2,\n maxDevices: 4,\n idleShutdownMinutes: 10,\n waitTimeoutSeconds: 120,\n} as const;\n\nexport const JANITOR_INTERVAL_MS = 60_000;\nexport const QUEUE_POLL_MS = 750;\n/** A set member with no row must stay orphaned this long before it is deleted, so a create in flight survives. */\nexport const ORPHAN_GRACE_MS = 5 * 60_000;\nexport const SIMCTL_TIMEOUT_MS = 120_000;\nexport const BOOT_TIMEOUT_MS = 300_000;\nexport const MAX_COMMAND_OUTPUT_CHARS = 8 * 1024 * 1024;\nexport const SCREENSHOT_MAX_PIXELS = 1200;\nexport const LOG_DEFAULT_SECONDS = 60;\nexport const LOG_DEFAULT_LINES = 200;\n/** A phone app's console: lines kept per device, and how long devicectl stays attached before it is stopped. */\nexport const CONSOLE_MAX_LINES = 5000;\nexport const CONSOLE_MAX_MS = 12 * 60 * 60_000;\n\n/** Fixed tool path: never the server's own PATH. */\nexport const IOS_TOOL_PATH = '/usr/bin:/bin:/usr/sbin:/sbin';\n\nexport const IOS_ERROR_CODES = [\n 'IOS_UNSUPPORTED_HOST',\n 'IOS_NO_XCODE',\n 'IOS_NO_RUNTIME',\n 'IOS_POOL_BUSY',\n 'IOS_NO_LEASE',\n 'IOS_LEASE_LOST',\n 'IOS_COMMAND_FAILED',\n 'IOS_INVALID_ARGUMENT',\n 'IOS_HELPER_UNAVAILABLE',\n 'IOS_ELEMENT_STALE',\n 'IOS_AMBIGUOUS',\n 'IOS_NO_MATCH',\n] as const;\n\n/** The resident Swift helper that reads accessibility and sends touches; built from source on first use. */\nexport const HELPER_PRODUCT = 'po-ios-sim-helper';\nexport const HELPER_PROTOCOL_VERSION = 1;\nexport const HELPER_SOURCE_DIRECTORY = 'native/sim-helper';\n/** Every file the helper build reads; their contents key the build cache. A contract test keeps this list complete. */\nexport const HELPER_SOURCES = [\n 'Package.swift',\n 'Sources/PoIosCore/Protocol.swift',\n 'Sources/PoIosCore/Compaction.swift',\n 'Sources/PoIosSimHelper/main.swift',\n 'Sources/PoIosSimHelper/PrivateApis.swift',\n 'Sources/PoIosSimHelper/Backends.swift',\n 'Tests/PoIosCoreTests/ProtocolTests.swift',\n 'Tests/PoIosCoreTests/CompactionTests.swift',\n] as const;\nexport const HELPER_NATIVE_DIRECTORY = 'native';\nexport const HELPER_BUILD_LOCK = 'helper-build';\nexport const HELPER_TIMEOUT_MS = 15_000;\nexport const HELPER_BUILD_TIMEOUT_MS = 10 * 60_000;\nexport const HELPER_MAX_RESTARTS = 3;\nexport const HELPER_RESTART_WINDOW_MS = 5 * 60_000;\nexport const HELPER_MAX_LINE_CHARS = 8 * 1024 * 1024;\n\nexport const WAIT_POLL_MS = 250;\nexport const WAIT_MAX_POLL_MS = 1000;\nexport const WAIT_DEFAULT_MS = 10_000;\nexport const SETTLE_DEFAULT_MS = 5000;\nexport const SETTLE_QUIET_MS = 500;\nexport const AMBIGUOUS_CANDIDATES = 5;\nexport const SWIPE_DEFAULT_MS = 300;\nexport const HARDWARE_BUTTONS = ['home', 'lock', 'siri', 'volumeUp', 'volumeDown'] as const;\n","import { defineServiceContract } from '@agimon-ai/po-core/extensionFile';\n\nimport { IOS_POOL_SERVICE } from '../constants/ios';\nimport type { IosPool } from '../services/devicePool/type';\n\n/** Bound once at the global level; every session leases from the same pool. */\nexport const IOS_POOL_CONTRACT = defineServiceContract<IosPool>(IOS_POOL_SERVICE, { scope: 'global' });\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'po/ios-pool': IosPool;\n }\n}\n"],"mappings":";;AACA,MAAa,cAAc;AAC3B,MAAa,mBAAmB;AAMhC,MAAa,2BAA2B;AACxC,MAAa,yBAAyB;AAEtC,MAAa,oBAAoB;CAC/B,WAAW;CACX,WAAW;CACX,YAAY;CACZ,qBAAqB;CACrB,oBAAoB;AACtB;AAEA,MAAa,sBAAsB;;AAGnC,MAAa,kBAAkB;AAC/B,MAAa,oBAAoB;AACjC,MAAa,kBAAkB;AAC/B,MAAa,2BAA2B;AACxC,MAAa,wBAAwB;;AAIrC,MAAa,oBAAoB;AACjC,MAAa,iBAAiB;;AAG9B,MAAa,gBAAgB;AAE7B,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,iBAAiB;AAE9B,MAAa,0BAA0B;;AAEvC,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AACA,MAAa,0BAA0B;AACvC,MAAa,oBAAoB;AACjC,MAAa,oBAAoB;AACjC,MAAa,0BAA0B;AAEvC,MAAa,2BAA2B;AACxC,MAAa,wBAAwB;AAGrC,MAAa,mBAAmB;AAChC,MAAa,kBAAkB;AAC/B,MAAa,oBAAoB;;;;ACvEjC,MAAa,qBAAA,GAAoBA,iCAAAA,sBAAAA,CAA+B,kBAAkB,EAAE,OAAO,SAAS,CAAC"}
@@ -18,6 +18,9 @@ const SIMCTL_TIMEOUT_MS = 12e4;
18
18
  const BOOT_TIMEOUT_MS = 3e5;
19
19
  const MAX_COMMAND_OUTPUT_CHARS = 8388608;
20
20
  const SCREENSHOT_MAX_PIXELS = 1200;
21
+ /** A phone app's console: lines kept per device, and how long devicectl stays attached before it is stopped. */
22
+ const CONSOLE_MAX_LINES = 5e3;
23
+ const CONSOLE_MAX_MS = 432e5;
21
24
  /** Fixed tool path: never the server's own PATH. */
22
25
  const IOS_TOOL_PATH = "/usr/bin:/bin:/usr/sbin:/sbin";
23
26
  const IOS_ERROR_CODES = [
@@ -62,6 +65,6 @@ const SETTLE_DEFAULT_MS = 5e3;
62
65
  /** Bound once at the global level; every session leases from the same pool. */
63
66
  const IOS_POOL_CONTRACT = defineServiceContract(IOS_POOL_SERVICE, { scope: "global" });
64
67
  //#endregion
65
- export { SETTLE_DEFAULT_MS as C, WAIT_MAX_POLL_MS as E, SCREENSHOT_MAX_PIXELS as S, WAIT_DEFAULT_MS as T, IOS_POOL_SERVICE as _, HELPER_MAX_LINE_CHARS as a, MAX_COMMAND_OUTPUT_CHARS as b, HELPER_RESTART_WINDOW_MS as c, HELPER_TIMEOUT_MS as d, IOS_DEVICE_NAME_PREFIX as f, IOS_POOL_DEFAULTS as g, IOS_PACKAGE as h, HELPER_BUILD_TIMEOUT_MS as i, HELPER_SOURCES as l, IOS_ERROR_CODES as m, BOOT_TIMEOUT_MS as n, HELPER_NATIVE_DIRECTORY as o, IOS_DEVICE_SET_DIRECTORY as p, HELPER_BUILD_LOCK as r, HELPER_PRODUCT as s, IOS_POOL_CONTRACT as t, HELPER_SOURCE_DIRECTORY as u, IOS_TOOL_PATH as v, SIMCTL_TIMEOUT_MS as w, ORPHAN_GRACE_MS as x, JANITOR_INTERVAL_MS as y };
68
+ export { ORPHAN_GRACE_MS as C, WAIT_DEFAULT_MS as D, SIMCTL_TIMEOUT_MS as E, WAIT_MAX_POLL_MS as O, MAX_COMMAND_OUTPUT_CHARS as S, SETTLE_DEFAULT_MS as T, IOS_PACKAGE as _, HELPER_BUILD_LOCK as a, IOS_TOOL_PATH as b, HELPER_NATIVE_DIRECTORY as c, HELPER_SOURCES as d, HELPER_SOURCE_DIRECTORY as f, IOS_ERROR_CODES as g, IOS_DEVICE_SET_DIRECTORY as h, CONSOLE_MAX_MS as i, HELPER_PRODUCT as l, IOS_DEVICE_NAME_PREFIX as m, BOOT_TIMEOUT_MS as n, HELPER_BUILD_TIMEOUT_MS as o, HELPER_TIMEOUT_MS as p, CONSOLE_MAX_LINES as r, HELPER_MAX_LINE_CHARS as s, IOS_POOL_CONTRACT as t, HELPER_RESTART_WINDOW_MS as u, IOS_POOL_DEFAULTS as v, SCREENSHOT_MAX_PIXELS as w, JANITOR_INTERVAL_MS as x, IOS_POOL_SERVICE as y };
66
69
 
67
- //# sourceMappingURL=contracts-D41ZfB5m.mjs.map
70
+ //# sourceMappingURL=contracts-DH0gdDYT.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts-DH0gdDYT.mjs","names":[],"sources":["../src/constants/ios.ts","../src/schemas/contracts.ts"],"sourcesContent":["export const IOS_NAMESPACE = 'ios';\nexport const IOS_PACKAGE = '@agimon-ai/po-ios';\nexport const IOS_POOL_SERVICE = 'po/ios-pool';\n\n/** Table prefix in the shared `po/db`. */\nexport const IOS_DB_PREFIX = 'ios';\n/** `<po home>/ios/devices` is the simulator device set Po owns; the person's own simulators live elsewhere. */\nexport const IOS_DIRECTORY = 'ios';\nexport const IOS_DEVICE_SET_DIRECTORY = 'devices';\nexport const IOS_DEVICE_NAME_PREFIX = 'po-pool-';\n\nexport const IOS_POOL_DEFAULTS = {\n minBooted: 0,\n maxBooted: 2,\n maxDevices: 4,\n idleShutdownMinutes: 10,\n waitTimeoutSeconds: 120,\n} as const;\n\nexport const JANITOR_INTERVAL_MS = 60_000;\nexport const QUEUE_POLL_MS = 750;\n/** A set member with no row must stay orphaned this long before it is deleted, so a create in flight survives. */\nexport const ORPHAN_GRACE_MS = 5 * 60_000;\nexport const SIMCTL_TIMEOUT_MS = 120_000;\nexport const BOOT_TIMEOUT_MS = 300_000;\nexport const MAX_COMMAND_OUTPUT_CHARS = 8 * 1024 * 1024;\nexport const SCREENSHOT_MAX_PIXELS = 1200;\nexport const LOG_DEFAULT_SECONDS = 60;\nexport const LOG_DEFAULT_LINES = 200;\n/** A phone app's console: lines kept per device, and how long devicectl stays attached before it is stopped. */\nexport const CONSOLE_MAX_LINES = 5000;\nexport const CONSOLE_MAX_MS = 12 * 60 * 60_000;\n\n/** Fixed tool path: never the server's own PATH. */\nexport const IOS_TOOL_PATH = '/usr/bin:/bin:/usr/sbin:/sbin';\n\nexport const IOS_ERROR_CODES = [\n 'IOS_UNSUPPORTED_HOST',\n 'IOS_NO_XCODE',\n 'IOS_NO_RUNTIME',\n 'IOS_POOL_BUSY',\n 'IOS_NO_LEASE',\n 'IOS_LEASE_LOST',\n 'IOS_COMMAND_FAILED',\n 'IOS_INVALID_ARGUMENT',\n 'IOS_HELPER_UNAVAILABLE',\n 'IOS_ELEMENT_STALE',\n 'IOS_AMBIGUOUS',\n 'IOS_NO_MATCH',\n] as const;\n\n/** The resident Swift helper that reads accessibility and sends touches; built from source on first use. */\nexport const HELPER_PRODUCT = 'po-ios-sim-helper';\nexport const HELPER_PROTOCOL_VERSION = 1;\nexport const HELPER_SOURCE_DIRECTORY = 'native/sim-helper';\n/** Every file the helper build reads; their contents key the build cache. A contract test keeps this list complete. */\nexport const HELPER_SOURCES = [\n 'Package.swift',\n 'Sources/PoIosCore/Protocol.swift',\n 'Sources/PoIosCore/Compaction.swift',\n 'Sources/PoIosSimHelper/main.swift',\n 'Sources/PoIosSimHelper/PrivateApis.swift',\n 'Sources/PoIosSimHelper/Backends.swift',\n 'Tests/PoIosCoreTests/ProtocolTests.swift',\n 'Tests/PoIosCoreTests/CompactionTests.swift',\n] as const;\nexport const HELPER_NATIVE_DIRECTORY = 'native';\nexport const HELPER_BUILD_LOCK = 'helper-build';\nexport const HELPER_TIMEOUT_MS = 15_000;\nexport const HELPER_BUILD_TIMEOUT_MS = 10 * 60_000;\nexport const HELPER_MAX_RESTARTS = 3;\nexport const HELPER_RESTART_WINDOW_MS = 5 * 60_000;\nexport const HELPER_MAX_LINE_CHARS = 8 * 1024 * 1024;\n\nexport const WAIT_POLL_MS = 250;\nexport const WAIT_MAX_POLL_MS = 1000;\nexport const WAIT_DEFAULT_MS = 10_000;\nexport const SETTLE_DEFAULT_MS = 5000;\nexport const SETTLE_QUIET_MS = 500;\nexport const AMBIGUOUS_CANDIDATES = 5;\nexport const SWIPE_DEFAULT_MS = 300;\nexport const HARDWARE_BUTTONS = ['home', 'lock', 'siri', 'volumeUp', 'volumeDown'] as const;\n","import { defineServiceContract } from '@agimon-ai/po-core/extensionFile';\n\nimport { IOS_POOL_SERVICE } from '../constants/ios';\nimport type { IosPool } from '../services/devicePool/type';\n\n/** Bound once at the global level; every session leases from the same pool. */\nexport const IOS_POOL_CONTRACT = defineServiceContract<IosPool>(IOS_POOL_SERVICE, { scope: 'global' });\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'po/ios-pool': IosPool;\n }\n}\n"],"mappings":";;AACA,MAAa,cAAc;AAC3B,MAAa,mBAAmB;AAMhC,MAAa,2BAA2B;AACxC,MAAa,yBAAyB;AAEtC,MAAa,oBAAoB;CAC/B,WAAW;CACX,WAAW;CACX,YAAY;CACZ,qBAAqB;CACrB,oBAAoB;AACtB;AAEA,MAAa,sBAAsB;;AAGnC,MAAa,kBAAkB;AAC/B,MAAa,oBAAoB;AACjC,MAAa,kBAAkB;AAC/B,MAAa,2BAA2B;AACxC,MAAa,wBAAwB;;AAIrC,MAAa,oBAAoB;AACjC,MAAa,iBAAiB;;AAG9B,MAAa,gBAAgB;AAE7B,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,iBAAiB;AAE9B,MAAa,0BAA0B;;AAEvC,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AACA,MAAa,0BAA0B;AACvC,MAAa,oBAAoB;AACjC,MAAa,oBAAoB;AACjC,MAAa,0BAA0B;AAEvC,MAAa,2BAA2B;AACxC,MAAa,wBAAwB;AAGrC,MAAa,mBAAmB;AAChC,MAAa,kBAAkB;AAC/B,MAAa,oBAAoB;;;;ACvEjC,MAAa,oBAAoB,sBAA+B,kBAAkB,EAAE,OAAO,SAAS,CAAC"}