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.
- package/LICENSE +1 -1
- package/README.md +11 -9
- package/cli/app-catalog.ts +77 -0
- package/cli/app-fonts.ts +4 -20
- package/cli/app-splash.ts +2 -18
- package/cli/bridge-flow-runner.ts +505 -139
- package/cli/cloud-client.ts +1 -4
- package/cli/cloud-session.ts +1 -4
- package/cli/cloud-test-result-files.ts +3 -0
- package/cli/cloud-test-tunnel.ts +2 -5
- package/cli/command-registry.ts +2 -0
- package/cli/commands/agent.ts +149 -23
- package/cli/commands/assert.ts +1 -4
- package/cli/commands/box/peach-command.ts +62 -0
- package/cli/commands/box/plane-share.ts +0 -70
- package/cli/commands/box/rnx-command.ts +1 -60
- package/cli/commands/box/search-command.ts +14 -0
- package/cli/commands/box.ts +2 -2
- package/cli/commands/control.ts +121 -27
- package/cli/commands/cpu-profile.ts +23 -10
- package/cli/commands/daemon.ts +1 -9
- package/cli/commands/detox.ts +26 -18
- package/cli/commands/device.ts +129 -1
- package/cli/commands/film.ts +25 -16
- package/cli/commands/flow.ts +9 -2
- package/cli/commands/inspect/actions.ts +75 -1
- package/cli/commands/inspect/core.ts +81 -2
- package/cli/commands/inspect/describe.ts +2 -6
- package/cli/commands/inspect/env.ts +1 -1
- package/cli/commands/inspect/settling.ts +20 -3
- package/cli/commands/inspect/shared.ts +1 -4
- package/cli/commands/inspect/sleep.ts +1 -1
- package/cli/commands/inspect.ts +16 -49
- package/cli/commands/install-desktop.ts +8 -6
- package/cli/commands/login.ts +3 -5
- package/cli/commands/maestro-generate.ts +1 -4
- package/cli/commands/maestro.ts +38 -21
- package/cli/commands/no-bridge-hint.ts +0 -14
- package/cli/commands/permissions.ts +2 -2
- package/cli/commands/platform.ts +13 -6
- package/cli/commands/screenshot.ts +6 -1
- package/cli/commands/skills.ts +1 -1
- package/cli/commands/test.ts +6 -2
- package/cli/commands/three-mode.ts +162 -19
- package/cli/commands/upload.ts +3 -18
- package/cli/current-sim.ts +0 -1
- package/cli/desktop-companion.ts +40 -8
- package/cli/drivers/playwright-provisioning.ts +1 -4
- package/cli/flow-export.ts +1 -8
- package/cli/flow-session.ts +0 -4
- package/cli/hints.ts +1 -16
- package/cli/inspect-notice-state.ts +0 -4
- package/cli/main.ts +2 -4
- package/cli/outbound-endpoints.ts +1 -24
- package/cli/parse-args.ts +1 -2
- package/cli/rnx-in-process.ts +3 -1
- package/cli/run-rnx-core.ts +4 -2
- package/cli/run-rnx.ts +18 -10
- package/cli/send-to-box.ts +1 -4
- package/cli/telemetry.ts +1 -1
- package/cli/ws-bridge.ts +1 -5
- package/detox/gestures.ts +20 -6
- package/detox/index.ts +379 -123
- package/detox/navigation-lifecycle.ts +22 -13
- package/dist-lib/agent-daemon-client.cjs +21 -15
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +3 -17
- package/dist-lib/agent-sessions.cjs +5 -4
- package/dist-lib/attached-projects.cjs +1 -77
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +11 -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 +7 -5
- package/dist-lib/bridge-contract-input.mjs +7 -5
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +30 -7
- package/dist-lib/capture-contract.mjs +30 -7
- 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 +17 -11
- package/dist-lib/cloud.mjs +17 -11
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +321 -122
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +427 -212
- package/dist-lib/host/fetch-proxy-handler.cjs +5 -28
- 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 +315 -58
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +67 -31
- package/dist-lib/menu.mjs +64 -28
- package/dist-lib/metro-fingerprint-registry.cjs +8 -4
- package/dist-lib/metro-fingerprint-registry.mjs +6 -4
- package/dist-lib/metro-production-bundle.cjs +2 -2
- package/dist-lib/metro-production-bundle.mjs +2 -2
- package/dist-lib/metro.cjs +8 -4
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +7 -4
- 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 +3 -13
- package/dist-lib/scripts/dev-server-scanner.cjs +5 -17
- package/dist-lib/sdk.cjs +129 -10
- package/dist-lib/sdk.mjs +127 -10
- package/dist-lib/skills.cjs +1635 -1121
- package/dist-lib/swift-compile.cjs +277 -70
- package/dist-lib/swift-compile.mjs +275 -70
- package/dist-lib/swift-package.cjs +17 -5
- package/dist-lib/swift-package.mjs +15 -4
- package/dist-lib/swift-submit.cjs +32 -8
- package/dist-lib/swift-submit.mjs +29 -7
- package/dist-lib/swift.cjs +30912 -577
- package/dist-lib/vite-kotlin.cjs +356 -0
- package/dist-lib/vite-swift.cjs +1743 -0
- package/dist-lib/vite.cjs +208 -1039
- package/kotlin/README.md +18 -0
- package/kotlin/Sources/androidx/annotation/Keep.kt +4 -0
- package/kotlin/Sources/dev/onejs/one/OneNativeSourceDispatch.kt +7 -0
- package/kotlin/Sources/dev/onejs/one/source/OneModule.kt +4 -0
- package/kotlin/Sources/org/json/JSON.kt +244 -0
- package/kotlin/toolchain.json +19 -0
- package/package.json +14 -2
- package/scripts/dev-server-scanner.ts +0 -18
- package/scripts/optional-demo-registry.ts +0 -17
- package/skills/contrast/SKILL.md +2 -2
- package/skills/peach-setup/SKILL.md +16 -0
- package/src/agent-daemon-client.ts +36 -22
- package/src/agent-identity.ts +0 -15
- package/src/agent-prompt.ts +12 -0
- package/src/attached-projects.ts +0 -72
- package/src/backend-origin.ts +10 -0
- package/src/bridge-contract-input.ts +2 -5
- package/src/bridge-contract.ts +2 -0
- package/src/capture-contract.ts +53 -11
- package/src/cloud.ts +4 -9
- package/src/dev-server-open.ts +0 -99
- package/src/home-paths.ts +2 -3
- package/src/host/agent-host.ts +82 -36
- package/src/host/bridge-host.ts +5 -11
- package/src/host/fetch-proxy-handler.ts +19 -43
- package/src/is-record.ts +4 -0
- package/src/menu.ts +82 -37
- package/src/metro-fingerprint-registry.ts +1 -4
- package/src/metro-production-bundle.ts +1 -1
- package/src/plist.ts +1 -4
- package/src/public-brand.ts +5 -3
- package/src/render-mode.ts +0 -12
- package/src/runtime-assets.ts +9 -2
- package/src/screenshots/compose.ts +7 -1
- package/src/screenshots/frame-compose.ts +21 -10
- package/src/screenshots/schema.ts +1 -4
- package/src/sim-client.ts +2 -4
- package/src/skills/builtin/maestro-test.ts +1 -4
- package/src/sleep.ts +4 -0
- package/src/swift-compile.ts +209 -47
- package/src/swift-icu.ts +140 -0
- package/src/swift-package.ts +26 -2
- package/src/swift-submit.ts +84 -4
- package/src/swift.ts +2 -0
- package/src/vite-plugin-kotlin.ts +376 -0
- package/src/vite-plugin-one.ts +224 -36
- package/src/vite-plugin-swift.ts +382 -96
- package/src/vite-plugin.ts +121 -134
- package/src/vite.d.ts +10 -0
- package/cli/resolve-assets.ts +0 -63
- package/src/rolldown-plugin-swift.ts +0 -244
- package/src/team-machine-prompt.ts +0 -73
package/kotlin/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# peachsim kotlin
|
|
2
|
+
|
|
3
|
+
The Android side of a One app's directly imported Kotlin in Peach. Owner spec:
|
|
4
|
+
[`specs/rnx-swift.md`](../../../specs/rnx-swift.md) (direct native source imports).
|
|
5
|
+
|
|
6
|
+
- `toolchain.json`: the pinned Kotlin compiler and the kotlinx-coroutines
|
|
7
|
+
Kotlin/Wasm klibs, with their sha256. `peachsim/vite-kotlin` fetches them once
|
|
8
|
+
into `~/.peach/kotlin/<version>`. kotlinc needs a Java runtime (17 or newer)
|
|
9
|
+
from `JAVA_HOME` or `PATH`, the one an Android build uses.
|
|
10
|
+
- `Sources/`: the Android and One declarations app Kotlin and One's generated
|
|
11
|
+
glue compile against: `org.json` with Android's parse and print rules,
|
|
12
|
+
`androidx.annotation.Keep`, `dev.onejs.one.OneNativeSourceDispatch` and
|
|
13
|
+
`dev.onejs.one.source.OneModule`.
|
|
14
|
+
|
|
15
|
+
The dev server compiles every `.kt` source of the app, One's glue for each and
|
|
16
|
+
a generated entry into one Kotlin/Wasm module, held to the Kotlin language
|
|
17
|
+
version React Native's Android build pins. Replay:
|
|
18
|
+
`scripts/debug/peach-one-native-source-guest.sh`.
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
package org.json
|
|
2
|
+
|
|
3
|
+
// the part of android's org.json that One's generated glue and app modules
|
|
4
|
+
// use, with android's parse and print rules: an integer literal parses as Int,
|
|
5
|
+
// or Long past Int, anything with a fraction or exponent as Double; a number
|
|
6
|
+
// whose value is integral prints without a fraction; '/' prints escaped.
|
|
7
|
+
|
|
8
|
+
class JSONException(message: String) : RuntimeException(message)
|
|
9
|
+
|
|
10
|
+
private class JSONTokener(private val text: String) {
|
|
11
|
+
private var at = 0
|
|
12
|
+
|
|
13
|
+
private fun skip() {
|
|
14
|
+
while (at < text.length && text[at].isWhitespace()) at++
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private fun next(): Char {
|
|
18
|
+
if (at >= text.length) throw JSONException("End of input at character $at of $text")
|
|
19
|
+
return text[at++]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private fun peek(): Char {
|
|
23
|
+
skip()
|
|
24
|
+
if (at >= text.length) throw JSONException("End of input at character $at of $text")
|
|
25
|
+
return text[at]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fun nextValue(): Any = when (peek()) {
|
|
29
|
+
'[' -> { at++; array() }
|
|
30
|
+
'{' -> { at++; objectValue() }
|
|
31
|
+
'"', '\'' -> string(next())
|
|
32
|
+
else -> literal()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private fun array(): JSONArray {
|
|
36
|
+
val result = JSONArray()
|
|
37
|
+
if (peek() == ']') { at++; return result }
|
|
38
|
+
while (true) {
|
|
39
|
+
result.put(nextValue())
|
|
40
|
+
when (peek().also { at++ }) {
|
|
41
|
+
']' -> return result
|
|
42
|
+
',', ';' -> continue
|
|
43
|
+
else -> throw JSONException("Unterminated array at character $at of $text")
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private fun objectValue(): JSONObject {
|
|
49
|
+
val result = JSONObject()
|
|
50
|
+
if (peek() == '}') { at++; return result }
|
|
51
|
+
while (true) {
|
|
52
|
+
val name = nextValue() as? String ?: throw JSONException("Names must be strings at character $at of $text")
|
|
53
|
+
if (peek() != ':' && text[at] != '=') throw JSONException("Expected ':' after $name at character $at of $text")
|
|
54
|
+
at++
|
|
55
|
+
if (text.getOrNull(at) == '>') at++
|
|
56
|
+
result.put(name, nextValue())
|
|
57
|
+
when (peek().also { at++ }) {
|
|
58
|
+
'}' -> return result
|
|
59
|
+
',', ';' -> continue
|
|
60
|
+
else -> throw JSONException("Unterminated object at character $at of $text")
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private fun string(quote: Char): String {
|
|
66
|
+
val out = StringBuilder()
|
|
67
|
+
while (true) {
|
|
68
|
+
val c = next()
|
|
69
|
+
if (c == quote) return out.toString()
|
|
70
|
+
if (c != '\\') { out.append(c); continue }
|
|
71
|
+
when (val escaped = next()) {
|
|
72
|
+
'u' -> {
|
|
73
|
+
if (at + 4 > text.length) throw JSONException("Unterminated escape sequence at character $at of $text")
|
|
74
|
+
out.append(text.substring(at, at + 4).toInt(16).toChar())
|
|
75
|
+
at += 4
|
|
76
|
+
}
|
|
77
|
+
't' -> out.append('\t')
|
|
78
|
+
'b' -> out.append('\b')
|
|
79
|
+
'n' -> out.append('\n')
|
|
80
|
+
'r' -> out.append('\r')
|
|
81
|
+
'f' -> out.append('\u000c')
|
|
82
|
+
else -> out.append(escaped)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private fun literal(): Any {
|
|
88
|
+
val start = at
|
|
89
|
+
while (at < text.length && text[at] !in "\r\n\t ,:#/\\;=[]{}\"'") at++
|
|
90
|
+
val word = text.substring(start, at)
|
|
91
|
+
if (word.isEmpty()) throw JSONException("Expected literal value at character $at of $text")
|
|
92
|
+
when (word.lowercase()) {
|
|
93
|
+
"null" -> return JSONObject.NULL
|
|
94
|
+
"true" -> return true
|
|
95
|
+
"false" -> return false
|
|
96
|
+
}
|
|
97
|
+
if (word.none { it == '.' || it == 'e' || it == 'E' }) {
|
|
98
|
+
val long = word.toLongOrNull()
|
|
99
|
+
if (long != null) return if (long in Int.MIN_VALUE..Int.MAX_VALUE) long.toInt() else long
|
|
100
|
+
}
|
|
101
|
+
return word.toDoubleOrNull() ?: word
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private fun quote(value: String, out: StringBuilder) {
|
|
106
|
+
out.append('"')
|
|
107
|
+
for (c in value) {
|
|
108
|
+
when (c) {
|
|
109
|
+
'"', '\\', '/' -> out.append('\\').append(c)
|
|
110
|
+
'\t' -> out.append("\\t")
|
|
111
|
+
'\b' -> out.append("\\b")
|
|
112
|
+
'\n' -> out.append("\\n")
|
|
113
|
+
'\r' -> out.append("\\r")
|
|
114
|
+
'\u000c' -> out.append("\\f")
|
|
115
|
+
else -> if (c.code <= 0x1f) out.append("\\u").append(c.code.toString(16).padStart(4, '0')) else out.append(c)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
out.append('"')
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private fun numberToString(number: Number): String {
|
|
122
|
+
val double = number.toDouble()
|
|
123
|
+
if (double.isNaN() || double.isInfinite()) throw JSONException("Forbidden numeric value: $number")
|
|
124
|
+
if (double == 0.0 && 1.0 / double < 0) return "-0"
|
|
125
|
+
val long = number.toLong()
|
|
126
|
+
if (double == long.toDouble()) return long.toString()
|
|
127
|
+
return number.toString()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private fun write(value: Any?, out: StringBuilder) {
|
|
131
|
+
when (value) {
|
|
132
|
+
null, JSONObject.NULL -> out.append("null")
|
|
133
|
+
is String -> quote(value, out)
|
|
134
|
+
is Boolean -> out.append(value)
|
|
135
|
+
is Number -> out.append(numberToString(value))
|
|
136
|
+
is JSONArray -> value.writeTo(out)
|
|
137
|
+
is JSONObject -> value.writeTo(out)
|
|
138
|
+
else -> quote(value.toString(), out)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
class JSONArray() {
|
|
143
|
+
private val values = ArrayList<Any?>()
|
|
144
|
+
|
|
145
|
+
constructor(json: String) : this() {
|
|
146
|
+
val parsed = JSONTokener(json).nextValue()
|
|
147
|
+
if (parsed !is JSONArray) throw JSONException("Value $json of type ${parsed::class.simpleName} cannot be converted to JSONArray")
|
|
148
|
+
values.addAll(parsed.values)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
constructor(collection: Collection<*>) : this() {
|
|
152
|
+
for (item in collection) values.add(JSONObject.wrap(item))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
fun length(): Int = values.size
|
|
156
|
+
|
|
157
|
+
fun opt(index: Int): Any? = values.getOrNull(index)
|
|
158
|
+
|
|
159
|
+
fun get(index: Int): Any {
|
|
160
|
+
if (index < 0 || index >= values.size) throw JSONException("Index $index out of range [0..${values.size})")
|
|
161
|
+
return values[index] ?: throw JSONException("Value at $index is null.")
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
fun put(value: Any?): JSONArray {
|
|
165
|
+
values.add(value)
|
|
166
|
+
return this
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
internal fun writeTo(out: StringBuilder) {
|
|
170
|
+
out.append('[')
|
|
171
|
+
values.forEachIndexed { index, value ->
|
|
172
|
+
if (index > 0) out.append(',')
|
|
173
|
+
write(value, out)
|
|
174
|
+
}
|
|
175
|
+
out.append(']')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
override fun toString(): String = StringBuilder().also { writeTo(it) }.toString()
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
class JSONObject() {
|
|
182
|
+
private val fields = LinkedHashMap<String, Any?>()
|
|
183
|
+
|
|
184
|
+
constructor(json: String) : this() {
|
|
185
|
+
val parsed = JSONTokener(json).nextValue()
|
|
186
|
+
if (parsed !is JSONObject) throw JSONException("Value $json of type ${parsed::class.simpleName} cannot be converted to JSONObject")
|
|
187
|
+
fields.putAll(parsed.fields)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
constructor(map: Map<*, *>) : this() {
|
|
191
|
+
for ((key, value) in map) fields[key as? String ?: throw NullPointerException("key == null")] = wrap(value)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
fun length(): Int = fields.size
|
|
195
|
+
|
|
196
|
+
fun has(name: String): Boolean = fields.containsKey(name)
|
|
197
|
+
|
|
198
|
+
fun opt(name: String): Any? = fields[name]
|
|
199
|
+
|
|
200
|
+
fun get(name: String): Any = fields[name] ?: throw JSONException("No value for $name")
|
|
201
|
+
|
|
202
|
+
fun put(name: String, value: Any?): JSONObject {
|
|
203
|
+
if (value == null) fields.remove(name) else {
|
|
204
|
+
if (value is Number) numberToString(value)
|
|
205
|
+
fields[name] = value
|
|
206
|
+
}
|
|
207
|
+
return this
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
fun keys(): Iterator<String> = fields.keys.iterator()
|
|
211
|
+
|
|
212
|
+
internal fun writeTo(out: StringBuilder) {
|
|
213
|
+
out.append('{')
|
|
214
|
+
var first = true
|
|
215
|
+
for ((key, value) in fields) {
|
|
216
|
+
if (!first) out.append(',')
|
|
217
|
+
first = false
|
|
218
|
+
quote(key, out)
|
|
219
|
+
out.append(':')
|
|
220
|
+
write(value, out)
|
|
221
|
+
}
|
|
222
|
+
out.append('}')
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
override fun toString(): String = StringBuilder().also { writeTo(it) }.toString()
|
|
226
|
+
|
|
227
|
+
companion object {
|
|
228
|
+
val NULL: Any = object {
|
|
229
|
+
override fun equals(other: Any?): Boolean = other == null || other === this
|
|
230
|
+
override fun hashCode(): Int = 0
|
|
231
|
+
override fun toString(): String = "null"
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
fun wrap(value: Any?): Any? = when (value) {
|
|
235
|
+
null -> NULL
|
|
236
|
+
is JSONArray, is JSONObject, NULL -> value
|
|
237
|
+
is Collection<*> -> JSONArray(value)
|
|
238
|
+
is Array<*> -> JSONArray(value.toList())
|
|
239
|
+
is Map<*, *> -> JSONObject(value)
|
|
240
|
+
is Boolean, is Byte, is Char, is Double, is Float, is Int, is Long, is Short, is String -> value
|
|
241
|
+
else -> null
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compiler": {
|
|
3
|
+
"version": "2.4.20",
|
|
4
|
+
"url": "https://github.com/JetBrains/kotlin/releases/download/v2.4.20/kotlin-compiler-2.4.20.zip",
|
|
5
|
+
"sha256": "59e9ca74c7904ef2c122b12114937673ccce68de820a663f0ed66ccf8799e0b7"
|
|
6
|
+
},
|
|
7
|
+
"libraries": [
|
|
8
|
+
{
|
|
9
|
+
"name": "kotlinx-coroutines-core-wasm-js-1.11.0.klib",
|
|
10
|
+
"url": "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-wasm-js/1.11.0/kotlinx-coroutines-core-wasm-js-1.11.0.klib",
|
|
11
|
+
"sha256": "1280b9f74850a4892a3641efa2a5779e5423b84aa7077cc60ddd50decbab921f"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "atomicfu-wasm-js-0.32.1.klib",
|
|
15
|
+
"url": "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/atomicfu-wasm-js/0.32.1/atomicfu-wasm-js-0.32.1.klib",
|
|
16
|
+
"sha256": "1bdc5a5216944b8f9a396d2f0c7df320b43d6921725baad1afc04cc8e2ae48e3"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "peachsim",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.579",
|
|
4
4
|
"description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
|
|
5
5
|
"author": "Tamagui LLC",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"default": "./dist-lib/auth/shared-session.cjs"
|
|
31
31
|
},
|
|
32
32
|
"./vite": {
|
|
33
|
-
"types": "./src/vite
|
|
33
|
+
"types": "./src/vite.d.ts",
|
|
34
34
|
"source": "./src/vite-plugin-one.ts",
|
|
35
35
|
"default": "./dist-lib/vite.cjs"
|
|
36
36
|
},
|
|
@@ -39,6 +39,16 @@
|
|
|
39
39
|
"source": "./src/swift.ts",
|
|
40
40
|
"default": "./dist-lib/swift.cjs"
|
|
41
41
|
},
|
|
42
|
+
"./vite-swift": {
|
|
43
|
+
"types": "./src/vite-plugin-swift.ts",
|
|
44
|
+
"source": "./src/vite-plugin-swift.ts",
|
|
45
|
+
"default": "./dist-lib/vite-swift.cjs"
|
|
46
|
+
},
|
|
47
|
+
"./vite-kotlin": {
|
|
48
|
+
"types": "./src/vite-plugin-kotlin.ts",
|
|
49
|
+
"source": "./src/vite-plugin-kotlin.ts",
|
|
50
|
+
"default": "./dist-lib/vite-kotlin.cjs"
|
|
51
|
+
},
|
|
42
52
|
"./swift-submit": {
|
|
43
53
|
"types": "./src/swift-submit.ts",
|
|
44
54
|
"source": "./src/swift-submit.ts",
|
|
@@ -260,6 +270,7 @@
|
|
|
260
270
|
"dist-lib/",
|
|
261
271
|
"src/",
|
|
262
272
|
"cli/",
|
|
273
|
+
"kotlin/",
|
|
263
274
|
"skills/",
|
|
264
275
|
"scripts/dev-server-scanner.ts",
|
|
265
276
|
"scripts/optional-demo-registry.ts",
|
|
@@ -283,6 +294,7 @@
|
|
|
283
294
|
"oxc-parser": "^0.112.0",
|
|
284
295
|
"playwright-core": "1.61.0",
|
|
285
296
|
"sucrase": "3.35.1",
|
|
297
|
+
"svgpath": "2.6.0",
|
|
286
298
|
"terser": "^5.49.0",
|
|
287
299
|
"ws": "^8.18.0"
|
|
288
300
|
},
|
|
@@ -707,22 +707,6 @@ function applyManifest(
|
|
|
707
707
|
return result
|
|
708
708
|
}
|
|
709
709
|
|
|
710
|
-
export function __applyManifestForTests(
|
|
711
|
-
result: DiscoveredServer,
|
|
712
|
-
manifestBody: string,
|
|
713
|
-
buildIconProxyUrl?: (externalUrl: string) => string,
|
|
714
|
-
): DiscoveredServer {
|
|
715
|
-
return applyManifest(
|
|
716
|
-
result,
|
|
717
|
-
{
|
|
718
|
-
statusCode: 200,
|
|
719
|
-
body: manifestBody,
|
|
720
|
-
hostname: new URL(result.bundleUrl).hostname,
|
|
721
|
-
},
|
|
722
|
-
buildIconProxyUrl,
|
|
723
|
-
)
|
|
724
|
-
}
|
|
725
|
-
|
|
726
710
|
// ── name/icon enrichment ────────────────────────────────────────────────────
|
|
727
711
|
// a server's display name + icon come ONLY from its expo manifest (GET / with
|
|
728
712
|
// expo-platform), which is far slower than the cheap signature probes: One apps
|
|
@@ -1115,8 +1099,6 @@ function isSootSimSelfServer(server: DiscoveredServer): boolean {
|
|
|
1115
1099
|
return false
|
|
1116
1100
|
}
|
|
1117
1101
|
|
|
1118
|
-
export const __isSootSimSelfServerForTests = isSootSimSelfServer
|
|
1119
|
-
|
|
1120
1102
|
// per-(port, pid) probe cache. as long as the same process still owns the
|
|
1121
1103
|
// port, its signature endpoints can't have changed, so we return the cached
|
|
1122
1104
|
// result without issuing any HTTP. negative results (null) are cached too,
|
|
@@ -94,20 +94,3 @@ export async function loadOptionalDemoApps(): Promise<OptionalDemoApp[]> {
|
|
|
94
94
|
export function optionalDemoAppsSync(): OptionalDemoApp[] {
|
|
95
95
|
return cached ?? []
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
/** replace the registry with a fixed list, and restore it on the returned
|
|
99
|
-
* handle. what the real registry holds depends on which third-party app
|
|
100
|
-
* checkouts and credential files happen to exist on the machine, so a test
|
|
101
|
-
* that reads it asserts on the developer's home directory rather than on the
|
|
102
|
-
* code. it passes on the box that has them and fails everywhere else. */
|
|
103
|
-
export function __withOptionalDemoAppsForTests(apps: OptionalDemoApp[]): {
|
|
104
|
-
restore: () => void
|
|
105
|
-
} {
|
|
106
|
-
const previous = cached
|
|
107
|
-
cached = apps
|
|
108
|
-
return {
|
|
109
|
-
restore: () => {
|
|
110
|
-
cached = previous
|
|
111
|
-
},
|
|
112
|
-
}
|
|
113
|
-
}
|
package/skills/contrast/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
|
|
10
10
|
overview of all available skills and CLI commands in this repo.
|
|
11
11
|
|
|
12
|
-
> this file is auto-generated by `bun scripts/generate
|
|
12
|
+
> this file is auto-generated by `bun scripts/generate/contrast-skill.ts`.
|
|
13
13
|
> to update, edit the source registries and re-run the generator.
|
|
14
14
|
|
|
15
15
|
## Peach CLI commands
|
|
@@ -50,7 +50,7 @@ automation, inspecting the render tree, and managing sims.
|
|
|
50
50
|
| `peach use` | select a connected sim |
|
|
51
51
|
| `peach skill` | install and inspect bundled peach agent skills |
|
|
52
52
|
| `peach claim` | take an exclusive lease on a sim |
|
|
53
|
-
| `peach agent` | attached projects
|
|
53
|
+
| `peach agent` | inspect messages, attached projects, and local agent sessions |
|
|
54
54
|
| `peach close` | close a connected sim |
|
|
55
55
|
| `peach setup` | configure optional local conveniences |
|
|
56
56
|
| `peach compat` | check package compatibility |
|
|
@@ -5,6 +5,22 @@ description: Get Peach connected to your React Native app with no project setup
|
|
|
5
5
|
|
|
6
6
|
# Peach setup
|
|
7
7
|
|
|
8
|
+
## receive inspect messages
|
|
9
|
+
|
|
10
|
+
after opening and pinning a sim, run this whenever you finish a turn and can
|
|
11
|
+
accept feedback from the simulator:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
peach agent listen
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
it returns one pending inspect message immediately, or waits for the next one,
|
|
18
|
+
then exits. handle the request and run it again. the printed context is meant
|
|
19
|
+
to be sufficient for the usual edit. only open the saved `describe.txt` when
|
|
20
|
+
you need more screen context, `inspect.json` for exact inspect data, or the
|
|
21
|
+
screenshot when color, clipping, spacing, or another visual detail matters.
|
|
22
|
+
`peach agent info <message-id>` prints the complete message and artifact paths.
|
|
23
|
+
|
|
8
24
|
you want to drive a React Native app with Peach from the CLI. this skill
|
|
9
25
|
takes you from a running development server to a connected, pinned sim that
|
|
10
26
|
every other Peach skill assumes exists. Peach requires no project setup or per-app
|
|
@@ -17,7 +17,11 @@ import { resolveSootsimInvocation, type Provider } from './agent-sessions.ts'
|
|
|
17
17
|
import { DEFAULT_SOOTSIM_BRIDGE_PORT } from './bridge-constants.ts'
|
|
18
18
|
import { shouldSkipPersistentDaemon } from './home-paths.ts'
|
|
19
19
|
import type { AgentEvent } from './agent-events.ts'
|
|
20
|
-
import type {
|
|
20
|
+
import type {
|
|
21
|
+
AgentInspectListenerStatus,
|
|
22
|
+
AgentInspectMessage,
|
|
23
|
+
AgentPromptEnvelope,
|
|
24
|
+
} from './agent-prompt.ts'
|
|
21
25
|
import type { AgentSession, AttachedProject } from './attached-projects.ts'
|
|
22
26
|
|
|
23
27
|
export interface AgentDaemonClientOptions {
|
|
@@ -74,7 +78,7 @@ export class AgentDaemonError extends Error {
|
|
|
74
78
|
type PendingEntry = {
|
|
75
79
|
resolve: (value: unknown) => void
|
|
76
80
|
reject: (err: Error) => void
|
|
77
|
-
timer: ReturnType<typeof setTimeout>
|
|
81
|
+
timer: ReturnType<typeof setTimeout> | null
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
type EventCallback = (payload: { sessionId: string; event: AgentEvent }) => void
|
|
@@ -165,16 +169,23 @@ export class AgentDaemonClient {
|
|
|
165
169
|
})
|
|
166
170
|
}
|
|
167
171
|
|
|
168
|
-
async
|
|
172
|
+
async listenForInspect(simId: string): Promise<AgentInspectMessage> {
|
|
173
|
+
return this.send<AgentInspectMessage>('agent:listen-inspect', { simId })
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async getInspectListenerStatus(simId: string): Promise<AgentInspectListenerStatus> {
|
|
177
|
+
return this.send<AgentInspectListenerStatus>('agent:get-inspect-listener-status', {
|
|
178
|
+
simId,
|
|
179
|
+
})
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async sendInspectMessage(
|
|
169
183
|
simId: string,
|
|
170
184
|
prompt: AgentPromptEnvelope,
|
|
171
|
-
): Promise<{ ok: true;
|
|
172
|
-
return this.send<{ ok: true;
|
|
173
|
-
'agent:send-
|
|
174
|
-
{
|
|
175
|
-
simId,
|
|
176
|
-
prompt,
|
|
177
|
-
},
|
|
185
|
+
): Promise<{ ok: true; queued: boolean; messageId: string }> {
|
|
186
|
+
return this.send<{ ok: true; queued: boolean; messageId: string }>(
|
|
187
|
+
'agent:send-inspect-message',
|
|
188
|
+
{ simId, prompt },
|
|
178
189
|
)
|
|
179
190
|
}
|
|
180
191
|
|
|
@@ -238,15 +249,18 @@ export class AgentDaemonClient {
|
|
|
238
249
|
}
|
|
239
250
|
const id = this.nextId++
|
|
240
251
|
return new Promise<T>((resolve, reject) => {
|
|
241
|
-
const timer =
|
|
242
|
-
this.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
252
|
+
const timer =
|
|
253
|
+
this.commandTimeoutMs > 0
|
|
254
|
+
? setTimeout(() => {
|
|
255
|
+
this.pending.delete(id)
|
|
256
|
+
reject(
|
|
257
|
+
new AgentDaemonError(
|
|
258
|
+
`${type} timed out after ${Math.round(this.commandTimeoutMs / 1000)}s`,
|
|
259
|
+
'TIMEOUT',
|
|
260
|
+
),
|
|
261
|
+
)
|
|
262
|
+
}, this.commandTimeoutMs)
|
|
263
|
+
: null
|
|
250
264
|
this.pending.set(id, {
|
|
251
265
|
resolve: resolve as (value: unknown) => void,
|
|
252
266
|
reject,
|
|
@@ -255,7 +269,7 @@ export class AgentDaemonClient {
|
|
|
255
269
|
try {
|
|
256
270
|
this.ws.send(JSON.stringify({ id, type, ...payload }))
|
|
257
271
|
} catch (err) {
|
|
258
|
-
clearTimeout(timer)
|
|
272
|
+
if (timer) clearTimeout(timer)
|
|
259
273
|
this.pending.delete(id)
|
|
260
274
|
reject(err instanceof Error ? err : new Error(String(err)))
|
|
261
275
|
}
|
|
@@ -293,7 +307,7 @@ export class AgentDaemonClient {
|
|
|
293
307
|
const entry = this.pending.get(msg.id)
|
|
294
308
|
if (!entry) return
|
|
295
309
|
this.pending.delete(msg.id)
|
|
296
|
-
clearTimeout(entry.timer)
|
|
310
|
+
if (entry.timer) clearTimeout(entry.timer)
|
|
297
311
|
if (msg.error) {
|
|
298
312
|
entry.reject(new AgentDaemonError(msg.error, msg.code))
|
|
299
313
|
} else {
|
|
@@ -305,7 +319,7 @@ export class AgentDaemonClient {
|
|
|
305
319
|
if (this.closed) return
|
|
306
320
|
this.closed = true
|
|
307
321
|
for (const [, entry] of this.pending) {
|
|
308
|
-
clearTimeout(entry.timer)
|
|
322
|
+
if (entry.timer) clearTimeout(entry.timer)
|
|
309
323
|
entry.reject(new AgentDaemonError('daemon disconnected', 'DISCONNECT'))
|
|
310
324
|
}
|
|
311
325
|
this.pending.clear()
|
package/src/agent-identity.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const TEAM_MACHINE_SESSION_RE = /^[A-Za-z0-9._:-]{1,160}$/
|
|
2
|
-
|
|
3
1
|
export function agentSessionIdFromCliIdentity(identity: string | null): string | null {
|
|
4
2
|
if (!identity) return null
|
|
5
3
|
const colon = identity.indexOf(':')
|
|
@@ -8,16 +6,3 @@ export function agentSessionIdFromCliIdentity(identity: string | null): string |
|
|
|
8
6
|
const value = identity.slice(colon + 1).trim()
|
|
9
7
|
return source === 'PEACH_CLI_IDENTITY' && value ? value : null
|
|
10
8
|
}
|
|
11
|
-
|
|
12
|
-
export function teamMachineSessionIdFromCliIdentity(
|
|
13
|
-
identity: string | null,
|
|
14
|
-
): string | null {
|
|
15
|
-
if (!identity?.startsWith('TM_SESSION:')) return null
|
|
16
|
-
const sessionId = identity.slice('TM_SESSION:'.length).trim()
|
|
17
|
-
if (!TEAM_MACHINE_SESSION_RE.test(sessionId)) return null
|
|
18
|
-
return sessionId
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function isValidTeamMachineSessionId(sessionId: string): boolean {
|
|
22
|
-
return TEAM_MACHINE_SESSION_RE.test(sessionId)
|
|
23
|
-
}
|
package/src/agent-prompt.ts
CHANGED
|
@@ -5,6 +5,18 @@ export interface AgentPromptEnvelope {
|
|
|
5
5
|
inspectTrace?: string
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export interface AgentInspectMessage {
|
|
9
|
+
id: string
|
|
10
|
+
simId: string
|
|
11
|
+
createdAt: string
|
|
12
|
+
prompt: AgentPromptEnvelope
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AgentInspectListenerStatus {
|
|
16
|
+
simId: string
|
|
17
|
+
listening: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
8
20
|
const ENVELOPE_MARKER = 'sootsim-agent-prompt-v1'
|
|
9
21
|
|
|
10
22
|
function cleanPromptText(value: string | undefined): string {
|