forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest-fast-dev-bundle.sh
More file actions
executable file
·194 lines (170 loc) · 9.33 KB
/
Copy pathtest-fast-dev-bundle.sh
File metadata and controls
executable file
·194 lines (170 loc) · 9.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MACOS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
source "$MACOS_DIR/scripts/fast-dev-bundle.sh"
TMP_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/omi-fast-dev-bundle.XXXXXX")"
cleanup() {
rm -rf "$TMP_ROOT"
}
trap cleanup EXIT
make_file() {
local path="$1"
local contents="$2"
mkdir -p "$(dirname "$TMP_ROOT/$path")"
printf '%s\n' "$contents" > "$TMP_ROOT/$path"
}
make_file run.sh 'launcher'
make_file Desktop/Package.swift 'package'
make_file Desktop/Sources/Resources/asset.txt 'asset'
make_file agent/src/index.ts 'agent'
make_file agent/node_modules/ignored.txt 'first'
make_file pi-mono-extension/index.ts 'extension'
first="$(omi_fast_bundle_fingerprint "$TMP_ROOT" bundle development yolo)"
second="$(omi_fast_bundle_fingerprint "$TMP_ROOT" bundle development yolo)"
test "$first" = "$second"
# Agent preparation stages the Node executable during a full bootstrap. The
# persisted stamp must be based on this completed state, not the pre-stage one.
make_file Desktop/Sources/Resources/node 'node-v1'
with_staged_node="$(omi_fast_bundle_fingerprint "$TMP_ROOT" bundle development yolo)"
test "$first" != "$with_staged_node"
# Working dependency trees are not packaged inputs; agent source is.
make_file agent/node_modules/ignored.txt 'second'
test "$with_staged_node" = "$(omi_fast_bundle_fingerprint "$TMP_ROOT" bundle development yolo)"
make_file agent/src/index.ts 'agent changed'
agent_changed="$(omi_fast_bundle_fingerprint "$TMP_ROOT" bundle development yolo)"
test "$with_staged_node" != "$agent_changed"
test "$agent_changed" != "$(omi_fast_bundle_fingerprint "$TMP_ROOT" bundle adhoc yolo)"
stamp="$TMP_ROOT/.dev/fast-bundles/bundle.stamp"
! omi_fast_bundle_stamp_matches "$stamp" "$agent_changed"
omi_fast_bundle_write_stamp "$stamp" "$agent_changed"
omi_fast_bundle_stamp_matches "$stamp" "$agent_changed"
! omi_fast_bundle_stamp_matches "$stamp" "$first"
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/missing.app" "$stamp" "$agent_changed")" = "no_installed_bundle"
mkdir -p "$TMP_ROOT/installed.app/Contents"
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/installed.app" "$TMP_ROOT/missing.stamp" "$agent_changed")" = "missing_fast_fingerprint"
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/installed.app" "$stamp" "$first")" = "fast_fingerprint_mismatch"
# Matching source inputs do not prove the installed bundle still carries the
# runtime they produced. An installed bundle whose agent payload is gone must
# never be declared reusable — patching its executable would relaunch an app
# that accepts chat turns and fails every one of them.
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/installed.app" "$stamp" "$agent_changed")" = "incomplete_runtime_payload"
install_agent_runtime_payload() {
local app="$1"
local relative
for relative in "${OMI_AGENT_RUNTIME_REQUIRED_FILES[@]}"; do
mkdir -p "$app/$(dirname "$relative")"
printf 'payload\n' > "$app/$relative"
done
for relative in "${OMI_AGENT_RUNTIME_REQUIRED_DIRS[@]}"; do
mkdir -p "$app/$relative"
printf 'payload\n' > "$app/$relative/.installed"
done
}
install_agent_runtime_payload "$TMP_ROOT/installed.app"
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/installed.app" "$stamp" "$agent_changed")" = "reusable"
# The failure this guard was written for: a build produced a bundle without
# Contents/Resources/pi-mono-extension, so pi-mono could not resolve the `omi`
# provider and exited 1 on every turn while chat looked healthy.
rm -rf "$TMP_ROOT/installed.app/Contents/Resources/pi-mono-extension"
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/installed.app" "$stamp" "$agent_changed")" = "incomplete_runtime_payload"
install_agent_runtime_payload "$TMP_ROOT/installed.app"
# An empty dependency tree fails at spawn exactly like a missing one.
rm -f "$TMP_ROOT/installed.app/Contents/Resources/agent/node_modules/.installed"
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/installed.app" "$stamp" "$agent_changed")" = "incomplete_runtime_payload"
install_agent_runtime_payload "$TMP_ROOT/installed.app"
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/installed.app" "$stamp" "$agent_changed")" = "reusable"
# A truncated copy (zero-byte entry point) is as unusable as an absent one.
: > "$TMP_ROOT/installed.app/Contents/Resources/agent/dist/index.js"
test "$(omi_fast_bundle_eligibility_reason "$TMP_ROOT/installed.app" "$stamp" "$agent_changed")" = "incomplete_runtime_payload"
install_agent_runtime_payload "$TMP_ROOT/installed.app"
# The build-time assertion names every missing component and points at the
# rebuild that repairs it, instead of letting the bundle install.
rm -rf "$TMP_ROOT/installed.app/Contents/Resources/pi-mono-extension"
assert_output="$TMP_ROOT/payload-assert.log"
if omi_assert_agent_runtime_payload "$TMP_ROOT/installed.app" "install" 2>"$assert_output"; then
echo "payload assertion accepted a bundle with no pi-mono-extension" >&2
exit 1
fi
grep -q 'Contents/Resources/pi-mono-extension/index.ts' "$assert_output"
grep -q 'OMI_FORCE_FULL_BUNDLE=1' "$assert_output"
install_agent_runtime_payload "$TMP_ROOT/installed.app"
omi_assert_agent_runtime_payload "$TMP_ROOT/installed.app" "install"
# Everything above is pure fingerprint and payload arithmetic and runs anywhere.
# Everything below invokes the real `run.sh`, which needs macOS — it resolves
# /Applications, codesigns, and drives launchctl. The Hygiene lane runs on
# ubuntu-latest, so gate the launcher half on the platform rather than dropping
# the whole file from CI: the static half is the part that catches a bundle
# shipped without its runtime payload, and it is worth running on every push.
if [[ "$(uname -s)" != "Darwin" ]]; then
echo "fast-dev-bundle fingerprint and payload tests passed (launcher contracts skipped: not macOS)"
exit 0
fi
# An agent's failed --fast-only probe must not tear down a running app, clean
# build output, or start services merely to discover that the named bundle does
# not exist. Exercise the real launcher with a unique missing app name.
fast_only_output="$TMP_ROOT/fast-only-launcher.log"
fast_only_name="omi-fast-only-contract-$$"
if HOME="$TMP_ROOT/home" OMI_APP_NAME="$fast_only_name" "$MACOS_DIR/run.sh" --yolo --fast-only >"$fast_only_output" 2>&1; then
echo "--fast-only unexpectedly succeeded for a missing bundle" >&2
exit 1
else
fast_only_status=$?
fi
test "$fast_only_status" = "3"
grep -q 'launch_mode=failed fast_reason=no_installed_bundle' "$fast_only_output"
if grep -qE 'Killing existing instances|Cleaning up conflicting app bundles|Starting Cloudflare|Starting Rust backend|Preparing agent runtime' "$fast_only_output"; then
echo "--fast-only performed launch side effects before rejecting a missing bundle" >&2
exit 1
fi
# A requested Rewind reseed must take the full install path. Fast-only is an
# inspection path and therefore rejects the combination before any side effect.
rewind_seed_fast_only_output="$TMP_ROOT/rewind-seed-fast-only.log"
if HOME="$TMP_ROOT/home" OMI_APP_NAME="omi-rewind-seed-fast-only-$$" OMI_FORCE_REWIND_SEED=1 \
"$MACOS_DIR/run.sh" --yolo --fast-only >"$rewind_seed_fast_only_output" 2>&1; then
echo "--fast-only unexpectedly accepted a forced Rewind seed" >&2
exit 1
else
rewind_seed_fast_only_status=$?
fi
test "$rewind_seed_fast_only_status" = "2"
grep -q -- '--fast-only cannot be combined' "$rewind_seed_fast_only_output"
if grep -qE 'Killing existing instances|Cleaning up conflicting app bundles|Starting Cloudflare|Starting Rust backend|Preparing agent runtime' "$rewind_seed_fast_only_output"; then
echo "forced Rewind seed performed launch side effects before rejecting --fast-only" >&2
exit 1
fi
# A detached launcher cannot own a tunnel: cleanup would terminate it as the
# script exits, leaving the relaunched app with a dead endpoint. Reject this
# configuration before probing or starting anything.
no_wait_output="$TMP_ROOT/no-wait-launcher.log"
if HOME="$TMP_ROOT/home" OMI_APP_NAME="omi-no-wait-contract-$$" OMI_SKIP_BACKEND=1 \
"$MACOS_DIR/run.sh" --fast-only --no-wait >"$no_wait_output" 2>&1; then
echo "--no-wait unexpectedly accepted a launcher-owned tunnel" >&2
exit 1
else
no_wait_status=$?
fi
test "$no_wait_status" = "2"
grep -q 'requires OMI_SKIP_BACKEND=1 and OMI_SKIP_TUNNEL=1' "$no_wait_output"
if grep -qE 'Killing existing instances|Starting Cloudflare|Starting Rust backend' "$no_wait_output"; then
echo "--no-wait performed launch side effects before rejecting its tunnel lifecycle" >&2
exit 1
fi
# The documented environment form must have exactly the same detached-launch
# contract as --no-wait. This lets agent-driven loops avoid a lingering
# launcher after the named bundle is ready for manual QA.
no_wait_env_output="$TMP_ROOT/no-wait-env-launcher.log"
if HOME="$TMP_ROOT/home" OMI_APP_NAME="omi-no-wait-env-contract-$$" OMI_SKIP_BACKEND=1 NO_WAIT=1 \
"$MACOS_DIR/run.sh" --fast-only >"$no_wait_env_output" 2>&1; then
echo "NO_WAIT=1 unexpectedly accepted a launcher-owned tunnel" >&2
exit 1
else
no_wait_env_status=$?
fi
test "$no_wait_env_status" = "2"
grep -q 'requires OMI_SKIP_BACKEND=1 and OMI_SKIP_TUNNEL=1' "$no_wait_env_output"
if grep -qE 'Killing existing instances|Starting Cloudflare|Starting Rust backend' "$no_wait_env_output"; then
echo "NO_WAIT=1 performed launch side effects before rejecting its tunnel lifecycle" >&2
exit 1
fi
echo "fast-dev-bundle fingerprint tests passed"