peachsim 0.1.577 → 0.1.579

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 (178) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +11 -9
  3. package/cli/app-catalog.ts +77 -0
  4. package/cli/app-fonts.ts +4 -20
  5. package/cli/app-splash.ts +2 -18
  6. package/cli/bridge-flow-runner.ts +505 -139
  7. package/cli/cloud-client.ts +1 -4
  8. package/cli/cloud-session.ts +1 -4
  9. package/cli/cloud-test-result-files.ts +3 -0
  10. package/cli/cloud-test-tunnel.ts +2 -5
  11. package/cli/command-registry.ts +2 -0
  12. package/cli/commands/agent.ts +149 -23
  13. package/cli/commands/assert.ts +1 -4
  14. package/cli/commands/box/peach-command.ts +62 -0
  15. package/cli/commands/box/plane-share.ts +0 -70
  16. package/cli/commands/box/rnx-command.ts +1 -60
  17. package/cli/commands/box/search-command.ts +14 -0
  18. package/cli/commands/box.ts +2 -2
  19. package/cli/commands/control.ts +121 -27
  20. package/cli/commands/cpu-profile.ts +23 -10
  21. package/cli/commands/daemon.ts +1 -9
  22. package/cli/commands/detox.ts +26 -18
  23. package/cli/commands/device.ts +129 -1
  24. package/cli/commands/film.ts +25 -16
  25. package/cli/commands/flow.ts +9 -2
  26. package/cli/commands/inspect/actions.ts +75 -1
  27. package/cli/commands/inspect/core.ts +81 -2
  28. package/cli/commands/inspect/describe.ts +2 -6
  29. package/cli/commands/inspect/env.ts +1 -1
  30. package/cli/commands/inspect/settling.ts +20 -3
  31. package/cli/commands/inspect/shared.ts +1 -4
  32. package/cli/commands/inspect/sleep.ts +1 -1
  33. package/cli/commands/inspect.ts +16 -49
  34. package/cli/commands/install-desktop.ts +8 -6
  35. package/cli/commands/login.ts +3 -5
  36. package/cli/commands/maestro-generate.ts +1 -4
  37. package/cli/commands/maestro.ts +38 -21
  38. package/cli/commands/no-bridge-hint.ts +0 -14
  39. package/cli/commands/permissions.ts +2 -2
  40. package/cli/commands/platform.ts +13 -6
  41. package/cli/commands/screenshot.ts +6 -1
  42. package/cli/commands/skills.ts +1 -1
  43. package/cli/commands/test.ts +6 -2
  44. package/cli/commands/three-mode.ts +162 -19
  45. package/cli/commands/upload.ts +3 -18
  46. package/cli/current-sim.ts +0 -1
  47. package/cli/desktop-companion.ts +40 -8
  48. package/cli/drivers/playwright-provisioning.ts +1 -4
  49. package/cli/flow-export.ts +1 -8
  50. package/cli/flow-session.ts +0 -4
  51. package/cli/hints.ts +1 -16
  52. package/cli/inspect-notice-state.ts +0 -4
  53. package/cli/main.ts +2 -4
  54. package/cli/outbound-endpoints.ts +1 -24
  55. package/cli/parse-args.ts +1 -2
  56. package/cli/rnx-in-process.ts +3 -1
  57. package/cli/run-rnx-core.ts +4 -2
  58. package/cli/run-rnx.ts +18 -10
  59. package/cli/send-to-box.ts +1 -4
  60. package/cli/telemetry.ts +1 -1
  61. package/cli/ws-bridge.ts +1 -5
  62. package/detox/gestures.ts +20 -6
  63. package/detox/index.ts +379 -123
  64. package/detox/navigation-lifecycle.ts +22 -13
  65. package/dist-lib/agent-daemon-client.cjs +21 -15
  66. package/dist-lib/agent-events.cjs +1 -1
  67. package/dist-lib/agent-identity.cjs +3 -17
  68. package/dist-lib/agent-sessions.cjs +5 -4
  69. package/dist-lib/attached-projects.cjs +1 -77
  70. package/dist-lib/auth/shared-session.cjs +1 -1
  71. package/dist-lib/backend-origin.cjs +11 -1
  72. package/dist-lib/beta.cjs +1 -1
  73. package/dist-lib/beta.mjs +1 -1
  74. package/dist-lib/bridge-constants.cjs +1 -1
  75. package/dist-lib/bridge-contract-input.cjs +7 -5
  76. package/dist-lib/bridge-contract-input.mjs +7 -5
  77. package/dist-lib/bridge-contract.cjs +1 -1
  78. package/dist-lib/bridge-contract.mjs +1 -1
  79. package/dist-lib/capture-contract.cjs +30 -7
  80. package/dist-lib/capture-contract.mjs +30 -7
  81. package/dist-lib/cli-constants.cjs +1 -1
  82. package/dist-lib/cloud-contract.cjs +1 -1
  83. package/dist-lib/cloud-contract.mjs +1 -1
  84. package/dist-lib/cloud-test-args.cjs +1 -1
  85. package/dist-lib/cloud-test-args.mjs +1 -1
  86. package/dist-lib/cloud.cjs +17 -11
  87. package/dist-lib/cloud.mjs +17 -11
  88. package/dist-lib/config.cjs +1 -1
  89. package/dist-lib/detox/index.cjs +321 -122
  90. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  91. package/dist-lib/home-paths.cjs +1 -1
  92. package/dist-lib/host/bridge-host.cjs +427 -212
  93. package/dist-lib/host/fetch-proxy-handler.cjs +5 -28
  94. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  95. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  96. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  97. package/dist-lib/host/websocket-proxy.cjs +1 -1
  98. package/dist-lib/index.cjs +315 -58
  99. package/dist-lib/jump-to-source-babel.cjs +1 -1
  100. package/dist-lib/jump-to-source-native.cjs +1 -1
  101. package/dist-lib/menu.cjs +67 -31
  102. package/dist-lib/menu.mjs +64 -28
  103. package/dist-lib/metro-fingerprint-registry.cjs +8 -4
  104. package/dist-lib/metro-fingerprint-registry.mjs +6 -4
  105. package/dist-lib/metro-production-bundle.cjs +2 -2
  106. package/dist-lib/metro-production-bundle.mjs +2 -2
  107. package/dist-lib/metro.cjs +8 -4
  108. package/dist-lib/profiles.cjs +1 -1
  109. package/dist-lib/public-brand.cjs +7 -4
  110. package/dist-lib/react-native-host-modules.cjs +1 -1
  111. package/dist-lib/react-native-host-modules.mjs +1 -1
  112. package/dist-lib/render-mode.cjs +3 -13
  113. package/dist-lib/scripts/dev-server-scanner.cjs +5 -17
  114. package/dist-lib/sdk.cjs +129 -10
  115. package/dist-lib/sdk.mjs +127 -10
  116. package/dist-lib/skills.cjs +1635 -1121
  117. package/dist-lib/swift-compile.cjs +277 -70
  118. package/dist-lib/swift-compile.mjs +275 -70
  119. package/dist-lib/swift-package.cjs +17 -5
  120. package/dist-lib/swift-package.mjs +15 -4
  121. package/dist-lib/swift-submit.cjs +32 -8
  122. package/dist-lib/swift-submit.mjs +29 -7
  123. package/dist-lib/swift.cjs +30912 -577
  124. package/dist-lib/vite-kotlin.cjs +356 -0
  125. package/dist-lib/vite-swift.cjs +1743 -0
  126. package/dist-lib/vite.cjs +208 -1039
  127. package/kotlin/README.md +18 -0
  128. package/kotlin/Sources/androidx/annotation/Keep.kt +4 -0
  129. package/kotlin/Sources/dev/onejs/one/OneNativeSourceDispatch.kt +7 -0
  130. package/kotlin/Sources/dev/onejs/one/source/OneModule.kt +4 -0
  131. package/kotlin/Sources/org/json/JSON.kt +244 -0
  132. package/kotlin/toolchain.json +19 -0
  133. package/package.json +14 -2
  134. package/scripts/dev-server-scanner.ts +0 -18
  135. package/scripts/optional-demo-registry.ts +0 -17
  136. package/skills/contrast/SKILL.md +2 -2
  137. package/skills/peach-setup/SKILL.md +16 -0
  138. package/src/agent-daemon-client.ts +36 -22
  139. package/src/agent-identity.ts +0 -15
  140. package/src/agent-prompt.ts +12 -0
  141. package/src/attached-projects.ts +0 -72
  142. package/src/backend-origin.ts +10 -0
  143. package/src/bridge-contract-input.ts +2 -5
  144. package/src/bridge-contract.ts +2 -0
  145. package/src/capture-contract.ts +53 -11
  146. package/src/cloud.ts +4 -9
  147. package/src/dev-server-open.ts +0 -99
  148. package/src/home-paths.ts +2 -3
  149. package/src/host/agent-host.ts +82 -36
  150. package/src/host/bridge-host.ts +5 -11
  151. package/src/host/fetch-proxy-handler.ts +19 -43
  152. package/src/is-record.ts +4 -0
  153. package/src/menu.ts +82 -37
  154. package/src/metro-fingerprint-registry.ts +1 -4
  155. package/src/metro-production-bundle.ts +1 -1
  156. package/src/plist.ts +1 -4
  157. package/src/public-brand.ts +5 -3
  158. package/src/render-mode.ts +0 -12
  159. package/src/runtime-assets.ts +9 -2
  160. package/src/screenshots/compose.ts +7 -1
  161. package/src/screenshots/frame-compose.ts +21 -10
  162. package/src/screenshots/schema.ts +1 -4
  163. package/src/sim-client.ts +2 -4
  164. package/src/skills/builtin/maestro-test.ts +1 -4
  165. package/src/sleep.ts +4 -0
  166. package/src/swift-compile.ts +209 -47
  167. package/src/swift-icu.ts +140 -0
  168. package/src/swift-package.ts +26 -2
  169. package/src/swift-submit.ts +84 -4
  170. package/src/swift.ts +2 -0
  171. package/src/vite-plugin-kotlin.ts +376 -0
  172. package/src/vite-plugin-one.ts +224 -36
  173. package/src/vite-plugin-swift.ts +382 -96
  174. package/src/vite-plugin.ts +121 -134
  175. package/src/vite.d.ts +10 -0
  176. package/cli/resolve-assets.ts +0 -63
  177. package/src/rolldown-plugin-swift.ts +0 -244
  178. package/src/team-machine-prompt.ts +0 -73
@@ -1,244 +0,0 @@
1
- // `.swift` handling for One's native rolldown engine: submit the owning
2
- // swiftpm package to `/api/swift-compile` and answer every `.swift` import
3
- // with the module that mounts the published artifact.
4
- //
5
- // this is the remote twin of `vite-plugin-swift.ts`. that plugin calls the
6
- // shared project-unit compiler and serves the artifact from dev-server
7
- // middleware. the native engine is its own rolldown instance with no
8
- // middleware seam, so this plugin compiles nothing in-process and serves
9
- // nothing. the artifact url the service answers is absolute (compile-cdn), so
10
- // there is nothing to serve. same compiler, same store, same hash, same
11
- // credential as the browser worker — one path, no second toolchain to install
12
- // for `one dev`.
13
- //
14
- // an app registers it through One's native plugin seam, not `config.plugins`
15
- // (which never reach the native engine):
16
- //
17
- // // vite.config.ts
18
- // export default {
19
- // plugins: [one({
20
- // native: {
21
- // bundler: 'vite',
22
- // bundlerOptions: {
23
- // plugins: [swiftRemotePlugin({
24
- // endpoint: 'https://contrast.dev',
25
- // assetReadToken: process.env.CONTRAST_CCDN_KEY,
26
- // })],
27
- // },
28
- // },
29
- // })],
30
- // }
31
- //
32
- // no babel anywhere in this path: resolveId and load only, emitting an ESM
33
- // module. offline `one dev` fails loud at the submit, the same as a browser
34
- // build without a credential; the standalone `peach` CLI keeps the local
35
- // toolchain plugin for that case.
36
-
37
- import fs from 'node:fs'
38
- import path from 'node:path'
39
- import {
40
- enumerateBundleImages,
41
- enumerateBundleJson,
42
- } from '../../sootsim-swift/src/bundleAssets'
43
- import { swiftEntryModuleEsm } from '../../sootsim-swift/src/entryModule'
44
- import { compileSwiftProject, httpSwiftCompileSubmit } from './swift-submit'
45
- import { entryRootId } from './vite-plugin-swift'
46
- import type { SwiftModuleAddress } from './swift-submit'
47
- import type { Plugin } from 'vite'
48
-
49
- const VIRTUAL_PREFIX = '\0peach-swift-remote:'
50
-
51
- export interface SwiftRemotePluginOptions {
52
- /** origin serving `/api/swift-compile` (the Contrast app). */
53
- endpoint: string
54
- /** a `ccdn_` API key or dev session token the compile verifier accepts. */
55
- assetReadToken: string
56
- /**
57
- * directory uploaded `.swift` imports resolve under. defaults to the
58
- * nearest `Package.swift` above each imported file — the swiftpm package
59
- * that owns it — which is the compile unit, exactly like the local host.
60
- * an app that keeps sources somewhere else names that package explicitly.
61
- */
62
- packagePath?: string
63
- }
64
-
65
- interface RemoteProject {
66
- packagePath: string
67
- address: SwiftModuleAddress | null
68
- }
69
-
70
- // one address per package per process: a failed submit keeps serving the
71
- // last published artifact (and warns) rather than failing the module, so
72
- // the edit that fixes the error still has a graph to rebuild.
73
- const projects = new Map<string, RemoteProject>()
74
-
75
- function projectFor(packagePath: string): RemoteProject {
76
- const existing = projects.get(packagePath)
77
- if (existing) return existing
78
- const created: RemoteProject = { packagePath, address: null }
79
- projects.set(packagePath, created)
80
- return created
81
- }
82
-
83
- // every file under a directory, posix-relative, skipping what can never be
84
- // a source, a manifest, or bundle content. a nested Package.swift is a
85
- // separate package with its own compile: its files belong to that unit.
86
- // `.build` holds tens of thousands of intermediates and no bundle content;
87
- // walking it per import would tax every reload.
88
- function packageFiles(root: string): string[] {
89
- const found: string[] = []
90
- const walk = (dir: string): void => {
91
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
92
- if (
93
- entry.name.startsWith('.') ||
94
- entry.name === 'node_modules' ||
95
- entry.name === '.build'
96
- )
97
- continue
98
- const full = path.join(dir, entry.name)
99
- if (entry.isDirectory()) {
100
- if (full !== root && fs.existsSync(path.join(full, 'Package.swift'))) continue
101
- walk(full)
102
- } else {
103
- found.push(path.relative(root, full).split(path.sep).join(path.posix.sep))
104
- }
105
- }
106
- }
107
- walk(root)
108
- return found
109
- }
110
-
111
- // the file map the service compiles: the package's `.swift` sources plus
112
- // its root manifest, keyed package-relative. the manifest is partitioning
113
- // input only — the service emits its own manifest that links every target
114
- // against its SwiftUI module — so a standard local package travels as is.
115
- function sourceFiles(packagePath: string): Record<string, string> {
116
- const files: Record<string, string> = {}
117
- for (const relative of packageFiles(packagePath)) {
118
- if (!relative.endsWith('.swift')) continue
119
- files[relative] = fs.readFileSync(
120
- path.join(packagePath, ...relative.split('/')),
121
- 'utf8',
122
- )
123
- }
124
- return files
125
- }
126
-
127
- // the bundle pack and the photo uploads, through the shared enumeration
128
- // both hosts pack with, so the collision winner here is the winner on the
129
- // local host too. binary bytes straight from disk: this host is node.
130
- function bundlePack(packagePath: string): {
131
- resources: Record<string, string>
132
- images: Record<string, { file: string; data: string }>
133
- watched: string[]
134
- } {
135
- const relative = packageFiles(packagePath)
136
- const disk = (file: string): string => path.join(packagePath, ...file.split('/'))
137
- const resources: Record<string, string> = {}
138
- const watched: string[] = []
139
- for (const { base, file } of enumerateBundleJson(relative)) {
140
- resources[base] = fs.readFileSync(disk(file)).toString('base64')
141
- watched.push(file)
142
- }
143
- const images: Record<string, { file: string; data: string }> = {}
144
- const byRelative = new Map(relative.map((file) => [file, disk(file)]))
145
- for (const { name, file } of enumerateBundleImages(relative, (candidate) => {
146
- const absolute = byRelative.get(candidate)
147
- if (!absolute || path.basename(absolute) !== 'Contents.json') return null
148
- try {
149
- return fs.readFileSync(absolute, 'utf8')
150
- } catch {
151
- return null
152
- }
153
- })) {
154
- const absolute = byRelative.get(file)
155
- if (!absolute) continue
156
- images[name] = {
157
- file: path.posix.basename(file),
158
- data: fs.readFileSync(absolute).toString('base64'),
159
- }
160
- watched.push(file)
161
- }
162
- return { resources, images, watched }
163
- }
164
-
165
- // the swiftpm package that owns an imported file: the nearest directory at
166
- // or above the file that holds a Package.swift. a `.swift` file with no
167
- // package above it (a pod, an xcode target) is refused loud rather than
168
- // compiled as the wrong unit.
169
- function packageFor(file: string, stop?: string): string {
170
- let dir = path.dirname(file)
171
- for (;;) {
172
- if (fs.existsSync(path.join(dir, 'Package.swift'))) return dir
173
- if ((stop !== undefined && dir === stop) || path.dirname(dir) === dir) break
174
- dir = path.dirname(dir)
175
- }
176
- throw new Error(
177
- `no Package.swift above ${file}; a .swift import needs a swiftpm package like the one in packages/sootsim-swift/example`,
178
- )
179
- }
180
-
181
- export function swiftRemotePlugin(options: SwiftRemotePluginOptions): Plugin {
182
- const submit = httpSwiftCompileSubmit({
183
- assetReadToken: options.assetReadToken,
184
- endpoint: options.endpoint,
185
- })
186
- if (!submit) {
187
- throw new Error(
188
- 'swiftRemotePlugin needs an assetReadToken: a build without a compile credential cannot compile .swift sources',
189
- )
190
- }
191
- return {
192
- name: 'peach-swift-remote',
193
- enforce: 'pre',
194
-
195
- async resolveId(source, importer) {
196
- if (source.startsWith(VIRTUAL_PREFIX)) return source
197
- if (!source.endsWith('.swift')) return null
198
- const resolved = await this.resolve(source, importer, { skipSelf: true })
199
- if (!resolved) throw new Error(`cannot resolve swift source ${source}`)
200
- return VIRTUAL_PREFIX + resolved.id
201
- },
202
-
203
- async load(id) {
204
- if (!id.startsWith(VIRTUAL_PREFIX)) return null
205
- const file = id.slice(VIRTUAL_PREFIX.length)
206
- if (!fs.existsSync(file)) throw new Error(`swift source ${file} no longer exists`)
207
- const packagePath = options.packagePath ?? packageFor(file)
208
- const project = projectFor(packagePath)
209
- const files = sourceFiles(packagePath)
210
- const entry = path.relative(packagePath, file).split(path.sep).join(path.posix.sep)
211
- for (const source of Object.keys(files)) {
212
- this.addWatchFile(path.join(packagePath, ...source.split('/')))
213
- }
214
- const pack = bundlePack(packagePath)
215
- for (const watched of pack.watched) {
216
- this.addWatchFile(path.join(packagePath, ...watched.split('/')))
217
- }
218
- try {
219
- project.address = await compileSwiftProject(
220
- submit,
221
- { files, resources: pack.resources, images: pack.images, entry },
222
- options.endpoint,
223
- )
224
- } catch (error) {
225
- // a compile error must not fail this module: the graph would stop
226
- // watching it and the fix would never rebuild. the last published
227
- // artifact keeps rendering while the diagnostic is reported here.
228
- if (!project.address) throw error
229
- this.warn(error instanceof Error ? error.message : String(error))
230
- }
231
- const address = project.address
232
- // every import mounts through the one entry: the artifact answers
233
- // whether it is a view or an app root at runtime, so the transform
234
- // never re-derives the conformance from source.
235
- return swiftEntryModuleEsm({
236
- url: address.url,
237
- hash: address.hash,
238
- rootId: entryRootId(packagePath, file),
239
- resources: address.imageUrls ?? {},
240
- bundleFiles: pack.resources,
241
- })
242
- },
243
- }
244
- }
@@ -1,73 +0,0 @@
1
- import { spawn } from 'node:child_process'
2
- import {
3
- isValidTeamMachineSessionId,
4
- teamMachineSessionIdFromCliIdentity,
5
- } from './agent-identity.ts'
6
- import type { AgentPromptEnvelope } from './agent-prompt.ts'
7
-
8
- export { teamMachineSessionIdFromCliIdentity } from './agent-identity.ts'
9
-
10
- export function formatTeamMachinePromptText(prompt: AgentPromptEnvelope): string {
11
- return typeof prompt.text === 'string' ? prompt.text.trim() : ''
12
- }
13
-
14
- function resolveTeamMachineCommand(explicit?: string): string {
15
- const fromArg = explicit?.trim()
16
- if (fromArg) return fromArg
17
- return 'tm'
18
- }
19
-
20
- export async function sendPromptToTeamMachineSession(input: {
21
- sessionId: string
22
- prompt: AgentPromptEnvelope
23
- command?: string
24
- timeoutMs?: number
25
- }): Promise<void> {
26
- const sessionId = input.sessionId.trim()
27
- if (!isValidTeamMachineSessionId(sessionId)) {
28
- throw new Error(`invalid Team Machine session id: ${sessionId || '<empty>'}`)
29
- }
30
- const text = formatTeamMachinePromptText(input.prompt)
31
- if (!text) {
32
- throw new Error('prompt text is empty')
33
- }
34
-
35
- const command = resolveTeamMachineCommand(input.command)
36
- const timeoutMs = input.timeoutMs ?? 15_000
37
- await new Promise<void>((resolve, reject) => {
38
- const child = spawn(command, ['send', sessionId, text], {
39
- stdio: ['ignore', 'ignore', 'pipe'],
40
- env: process.env,
41
- })
42
- let stderr = ''
43
- const timer = setTimeout(() => {
44
- try {
45
- child.kill('SIGTERM')
46
- } catch {}
47
- reject(new Error(`tm send timed out after ${Math.round(timeoutMs / 1000)}s`))
48
- }, timeoutMs)
49
-
50
- child.stderr?.setEncoding('utf8')
51
- child.stderr?.on('data', (chunk) => {
52
- if (stderr.length < 4000) stderr += String(chunk)
53
- })
54
- child.on('error', (err) => {
55
- clearTimeout(timer)
56
- reject(err)
57
- })
58
- child.on('close', (code, signal) => {
59
- clearTimeout(timer)
60
- if (code === 0) {
61
- resolve()
62
- return
63
- }
64
- const detail = stderr.trim()
65
- reject(
66
- new Error(
67
- detail ||
68
- `tm send exited with ${signal ? `signal ${signal}` : `code ${code ?? 'unknown'}`}`,
69
- ),
70
- )
71
- })
72
- })
73
- }