peachsim 0.1.637 → 0.1.638
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.
- package/README.md +8 -5
- package/cli/bridge-flow-runner.ts +442 -14
- package/cli/commands/inspect/core.ts +93 -24
- package/cli/commands/maestro.ts +2 -2
- package/cli/commands/serve.ts +13 -1
- package/cli/drivers/playwright-provisioning.ts +8 -16
- package/cli/drivers/playwright-sim-host.ts +3 -0
- package/cli/drivers/playwright.ts +1 -0
- package/cli/internal-child.ts +51 -8
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +3 -2
- package/dist-lib/bridge-contract-input.mjs +3 -2
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +4 -2
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +76 -20
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +78 -20
- package/dist-lib/sdk.mjs +77 -20
- package/dist-lib/skills.cjs +394 -62
- package/dist-lib/swift-compile.cjs +89 -7
- package/dist-lib/swift-compile.mjs +89 -7
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +122 -34
- package/dist-lib/vite-swift.cjs +89 -7
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/bridge-contract-input.ts +3 -2
- package/src/bridge-contract.ts +8 -0
- package/src/host/bridge-host.ts +5 -5
- package/src/native-seam-manifest.ts +4 -6
- package/src/swift-compile.ts +105 -9
package/src/host/bridge-host.ts
CHANGED
|
@@ -229,6 +229,8 @@ interface BridgeForwardedCommand {
|
|
|
229
229
|
export interface BridgeHostOptions {
|
|
230
230
|
/** use 0 for an OS-assigned port; startAsync returns the bound address. */
|
|
231
231
|
port?: number
|
|
232
|
+
/** listener address; defaults to 127.0.0.1. */
|
|
233
|
+
host?: string
|
|
232
234
|
openUrl?: (url: string, options?: OpenUrlOptions) => Promise<void> | void
|
|
233
235
|
/** Contrast-specific excludes for the agent host's dev-server scan. passed
|
|
234
236
|
* through to AgentHost; see packages/peach-engine/src/dev-scan-excludes.ts
|
|
@@ -404,6 +406,7 @@ export class SootSimBridgeHost {
|
|
|
404
406
|
// of reconnecting the zombie straight back in.
|
|
405
407
|
private static SIM_IDLE_REAP_TTL_MS = 30 * 60_000
|
|
406
408
|
|
|
409
|
+
private bindHost: string
|
|
407
410
|
private preferredPort: number
|
|
408
411
|
private portFallbackCount: number
|
|
409
412
|
private shouldWriteLockfile: boolean
|
|
@@ -438,6 +441,7 @@ export class SootSimBridgeHost {
|
|
|
438
441
|
private static SCAN_FRESH_MS = 2000
|
|
439
442
|
|
|
440
443
|
constructor(opts: BridgeHostOptions = {}) {
|
|
444
|
+
this.bindHost = opts.host ?? '127.0.0.1'
|
|
441
445
|
this.preferredPort = opts.port ?? DEFAULT_SOOTSIM_BRIDGE_PORT
|
|
442
446
|
this.port = this.preferredPort
|
|
443
447
|
// default off — callers that want the lockfile (peach serve) opt in.
|
|
@@ -533,11 +537,7 @@ export class SootSimBridgeHost {
|
|
|
533
537
|
}
|
|
534
538
|
server.once('error', onError)
|
|
535
539
|
|
|
536
|
-
|
|
537
|
-
// daemon serves the active runtime's dist as plain static files —
|
|
538
|
-
// never expose that to LAN peers. tests + the electron renderer use
|
|
539
|
-
// 127.0.0.1 explicitly to avoid the localhost-vs-::1 DNS coinflip.
|
|
540
|
-
server.listen(port, '127.0.0.1', () => {
|
|
540
|
+
server.listen(port, this.bindHost, () => {
|
|
541
541
|
if (settled) return
|
|
542
542
|
const address = server.address()
|
|
543
543
|
if (!address || typeof address === 'string') {
|
|
@@ -153,15 +153,13 @@ export const NATIVE_SEAM_MANIFEST: NativeSeamEntry[] = [
|
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
pkg: '@bam.tech/react-native-image-resizer',
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
// for documentation parity; vite-path redirect would key on
|
|
160
|
-
// `NativeImageResizer`.
|
|
156
|
+
// a Metro bundle reaches the same seam through the ImageResizer
|
|
157
|
+
// TurboModule that `stubs/bam-react-native-image-resizer-register.ts`
|
|
158
|
+
// registers.
|
|
161
159
|
seamBasenames: ['NativeImageResizer'],
|
|
162
160
|
target: seamPath('bam-react-native-image-resizer'),
|
|
163
161
|
notes:
|
|
164
|
-
'ImageResizer TurboModule
|
|
162
|
+
'ImageResizer TurboModule following ios/ImageResizer.mm: loader decode, rotation, scaling, and the file written to the app container',
|
|
165
163
|
},
|
|
166
164
|
{
|
|
167
165
|
pkg: 'react-native-adjust',
|
package/src/swift-compile.ts
CHANGED
|
@@ -224,8 +224,8 @@ export function swiftArtifactHash(
|
|
|
224
224
|
moduleRoot: string,
|
|
225
225
|
): string {
|
|
226
226
|
const hash = createHash('sha256')
|
|
227
|
-
//
|
|
228
|
-
hash.update(`swift-compile/
|
|
227
|
+
// v3: sources compile with os(iOS) true on code lines (swiftSourceAsIOS)
|
|
228
|
+
hash.update(`swift-compile/v3\n${release}\n`)
|
|
229
229
|
if (input.oneModule) hash.update('one-module\n')
|
|
230
230
|
hash.update(linkedModuleDigest(moduleRoot))
|
|
231
231
|
for (const file of Object.keys(input.files).sort()) {
|
|
@@ -347,15 +347,111 @@ function syncSwiftTree(base: string, files: Map<string, string>): void {
|
|
|
347
347
|
// every iOS branch of the app would compile out. a condition line names iOS
|
|
348
348
|
// as `true` padded to the same length, so diagnostics keep their columns;
|
|
349
349
|
// os(WASI) still holds for code written for wasm. only `#if` and `#elseif`
|
|
350
|
-
// lines change
|
|
351
|
-
|
|
350
|
+
// lines that begin in code change: a line inside a string literal or a block
|
|
351
|
+
// comment is content. the artifact hash stays over the original text.
|
|
352
|
+
const DIRECTIVE = /^[ \t]*#(?:if|elseif)\b/
|
|
352
353
|
const OS_IOS = /\bos\(\s*iOS\s*\)/g
|
|
353
354
|
export function swiftSourceAsIOS(source: string): string {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
355
|
+
const code = swiftCodeLineStarts(source)
|
|
356
|
+
let offset = 0
|
|
357
|
+
return source
|
|
358
|
+
.split('\n')
|
|
359
|
+
.map((line) => {
|
|
360
|
+
const start = offset
|
|
361
|
+
offset += line.length + 1
|
|
362
|
+
if (!code.has(start) || !DIRECTIVE.test(line)) return line
|
|
363
|
+
return line.replace(OS_IOS, (match) => 'true'.padEnd(match.length))
|
|
364
|
+
})
|
|
365
|
+
.join('\n')
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// the offsets of the lines that begin in code, from a scan of Swift's lexical
|
|
369
|
+
// contexts: nested block comments, line comments, string literals (single and
|
|
370
|
+
// multiline, raw with any number of #, interpolations holding code and
|
|
371
|
+
// strings of their own) and #/ /# regex literals. a bare /regex/ literal
|
|
372
|
+
// reads as code.
|
|
373
|
+
type Lexical =
|
|
374
|
+
| { kind: 'code'; parens: number }
|
|
375
|
+
| { kind: 'block'; depth: number }
|
|
376
|
+
| { kind: 'string'; hashes: number; multiline: boolean }
|
|
377
|
+
| { kind: 'regex'; hashes: number }
|
|
378
|
+
function swiftCodeLineStarts(source: string): Set<number> {
|
|
379
|
+
const starts = new Set<number>()
|
|
380
|
+
const stack: Lexical[] = [{ kind: 'code', parens: 0 }]
|
|
381
|
+
const hashesAt = (at: number) => {
|
|
382
|
+
let end = at
|
|
383
|
+
while (source[end] === '#') end++
|
|
384
|
+
return end - at
|
|
385
|
+
}
|
|
386
|
+
const closes = (at: number, hashes: number) => source.startsWith('#'.repeat(hashes), at)
|
|
387
|
+
let i = 0
|
|
388
|
+
while (i < source.length) {
|
|
389
|
+
const top = stack[stack.length - 1]
|
|
390
|
+
if ((i === 0 || source[i - 1] === '\n') && top.kind === 'code' && stack.length === 1)
|
|
391
|
+
starts.add(i)
|
|
392
|
+
const char = source[i]
|
|
393
|
+
if (top.kind === 'block') {
|
|
394
|
+
if (source.startsWith('/*', i)) {
|
|
395
|
+
top.depth++
|
|
396
|
+
i += 2
|
|
397
|
+
} else if (source.startsWith('*/', i)) {
|
|
398
|
+
if (--top.depth === 0) stack.pop()
|
|
399
|
+
i += 2
|
|
400
|
+
} else i++
|
|
401
|
+
continue
|
|
402
|
+
}
|
|
403
|
+
if (top.kind === 'string') {
|
|
404
|
+
if (char === '\\' && closes(i + 1, top.hashes)) {
|
|
405
|
+
const after = i + 1 + top.hashes
|
|
406
|
+
if (source[after] === '(') {
|
|
407
|
+
stack.push({ kind: 'code', parens: 0 })
|
|
408
|
+
i = after + 1
|
|
409
|
+
} else i = after + 1
|
|
410
|
+
continue
|
|
411
|
+
}
|
|
412
|
+
const quote = top.multiline ? '"""' : '"'
|
|
413
|
+
if (source.startsWith(quote, i) && closes(i + quote.length, top.hashes)) {
|
|
414
|
+
stack.pop()
|
|
415
|
+
i += quote.length + top.hashes
|
|
416
|
+
} else i++
|
|
417
|
+
continue
|
|
418
|
+
}
|
|
419
|
+
if (top.kind === 'regex') {
|
|
420
|
+
if (char === '/' && closes(i + 1, top.hashes)) {
|
|
421
|
+
stack.pop()
|
|
422
|
+
i += 1 + top.hashes
|
|
423
|
+
} else i++
|
|
424
|
+
continue
|
|
425
|
+
}
|
|
426
|
+
if (source.startsWith('//', i)) {
|
|
427
|
+
const end = source.indexOf('\n', i)
|
|
428
|
+
i = end === -1 ? source.length : end
|
|
429
|
+
} else if (source.startsWith('/*', i)) {
|
|
430
|
+
stack.push({ kind: 'block', depth: 1 })
|
|
431
|
+
i += 2
|
|
432
|
+
} else if (char === '"' || char === '#') {
|
|
433
|
+
const hashes = hashesAt(i)
|
|
434
|
+
const at = i + hashes
|
|
435
|
+
if (source.startsWith('"""', at)) {
|
|
436
|
+
stack.push({ kind: 'string', hashes, multiline: true })
|
|
437
|
+
i = at + 3
|
|
438
|
+
} else if (source[at] === '"') {
|
|
439
|
+
stack.push({ kind: 'string', hashes, multiline: false })
|
|
440
|
+
i = at + 1
|
|
441
|
+
} else if (hashes > 0 && source[at] === '/') {
|
|
442
|
+
stack.push({ kind: 'regex', hashes })
|
|
443
|
+
i = at + 1
|
|
444
|
+
} else i = Math.max(at, i + 1)
|
|
445
|
+
} else if (char === '(') {
|
|
446
|
+
top.parens++
|
|
447
|
+
i++
|
|
448
|
+
} else if (char === ')') {
|
|
449
|
+
if (top.parens === 0 && stack.length > 1) stack.pop()
|
|
450
|
+
else top.parens--
|
|
451
|
+
i++
|
|
452
|
+
} else i++
|
|
453
|
+
}
|
|
454
|
+
return starts
|
|
359
455
|
}
|
|
360
456
|
|
|
361
457
|
const compiledSource = (file: string, contents: string) =>
|