omnilane 0.20.0 → 0.21.0
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +12 -1
- package/README.ja.md +9 -3
- package/README.ko.md +9 -3
- package/README.md +9 -3
- package/README.zh-CN.md +9 -3
- package/README.zh-TW.md +9 -3
- package/VERSION +1 -1
- package/bin/omnilane +5 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/scripts/dispatch.sh +55 -7
- package/scripts/jobs.sh +24 -12
- package/scripts/lib/goal-loop.sh +776 -0
- package/scripts/lib/job-worker.sh +98 -37
- package/scripts/lib/live-protocol.sh +70 -0
- package/scripts/runners/run-gemini.sh +109 -0
|
@@ -7,6 +7,8 @@ set -euo pipefail
|
|
|
7
7
|
# Runtime-relative shared library.
|
|
8
8
|
# shellcheck disable=SC1091
|
|
9
9
|
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
|
|
10
|
+
# shellcheck disable=SC1091
|
|
11
|
+
source "$OMNILANE_REPO/scripts/lib/live-protocol.sh"
|
|
10
12
|
|
|
11
13
|
[[ $# -eq 7 ]] || { echo "omnilane: internal job worker received invalid arguments" >&2; exit 2; }
|
|
12
14
|
VENDOR="$1"; MODE="$2"; WORKDIR="$3"; MODEL="$4"; EFFORT="$5"
|
|
@@ -70,43 +72,72 @@ run_single_shot() {
|
|
|
70
72
|
return "$rc"
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
SESSION_MODE="${OMNILANE_SESSION_MODE:-auto}"
|
|
76
|
+
IDLE_TIMEOUT="${OMNILANE_IDLE_TIMEOUT:-900}"
|
|
77
|
+
LIVE_REQUIRED="${OMNILANE_LIVE_REQUIRED:-0}"
|
|
78
|
+
[[ "$SESSION_MODE" == "auto" || "$SESSION_MODE" == "live" || "$SESSION_MODE" == "single-shot" ]] || {
|
|
79
|
+
echo "omnilane: invalid worker session mode" >&2; exit 2
|
|
80
|
+
}
|
|
81
|
+
[[ "$IDLE_TIMEOUT" =~ ^(0|[1-9][0-9]*)$ ]] || {
|
|
82
|
+
echo "omnilane: invalid worker idle timeout" >&2; exit 2
|
|
83
|
+
}
|
|
84
|
+
[[ "$LIVE_REQUIRED" == "0" || "$LIVE_REQUIRED" == "1" ]] || {
|
|
85
|
+
echo "omnilane: invalid worker live requirement" >&2; exit 2
|
|
86
|
+
}
|
|
87
|
+
if [[ "$SESSION_MODE" == "auto" ]]; then
|
|
88
|
+
if live_vendor_capable "$VENDOR"; then SESSION_MODE="live"; else SESSION_MODE="single-shot"; fi
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
if [[ "$SESSION_MODE" == "single-shot" ]]; then
|
|
74
92
|
set +e
|
|
75
|
-
|
|
93
|
+
if live_vendor_capable "$VENDOR"; then
|
|
94
|
+
run_single_shot "omnilane: vendor '$VENDOR' was resolved to single-shot mode"
|
|
95
|
+
else
|
|
96
|
+
run_single_shot "omnilane: vendor '$VENDOR' is not live-capable; ran in single-shot mode"
|
|
97
|
+
fi
|
|
76
98
|
rc=$?
|
|
77
99
|
set -e
|
|
78
100
|
exit "$rc"
|
|
79
101
|
fi
|
|
80
102
|
|
|
103
|
+
if ! live_vendor_capable "$VENDOR"; then
|
|
104
|
+
echo "omnilane: vendor '$VENDOR' cannot run required live session; live-capable vendors: $(live_capable_vendors)" >&2
|
|
105
|
+
exit 2
|
|
106
|
+
fi
|
|
107
|
+
|
|
81
108
|
JOB_DIR="${OUTPUT_FILE%/*}"
|
|
82
109
|
JOB_ID="${JOB_DIR##*/}"
|
|
83
110
|
INBOX_FIFO="$JOB_DIR/inbox.fifo"
|
|
111
|
+
RUNNER_INBOX_FIFO="$JOB_DIR/runner-inbox.fifo"
|
|
84
112
|
HOLDER_PID_FILE="$JOB_DIR/inbox.holder.pid"
|
|
85
113
|
READY_FILE="$JOB_DIR/inbox.ready"
|
|
86
114
|
EVENTS_FILE="${OUTPUT_FILE}.events.jsonl"
|
|
87
115
|
EVENTS_ALIAS="$JOB_DIR/events.jsonl"
|
|
88
116
|
close_requested=0
|
|
89
|
-
|
|
117
|
+
close_reason=""
|
|
118
|
+
runner_writer_open=0
|
|
119
|
+
inbox_open=0
|
|
120
|
+
events_reader_open=0
|
|
90
121
|
runner_pid=""
|
|
91
122
|
|
|
92
123
|
# Invoked by the EXIT trap below.
|
|
93
124
|
# shellcheck disable=SC2329
|
|
94
125
|
cleanup_live_mailbox() {
|
|
95
|
-
if [[ "$
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
rm "$READY_FILE" "$HOLDER_PID_FILE" "$INBOX_FIFO" 2>/dev/null || true
|
|
126
|
+
if [[ "$runner_writer_open" -eq 1 ]]; then exec 3>&-; runner_writer_open=0; fi
|
|
127
|
+
if [[ "$inbox_open" -eq 1 ]]; then exec 4>&-; inbox_open=0; fi
|
|
128
|
+
if [[ "$events_reader_open" -eq 1 ]]; then exec 5<&-; events_reader_open=0; fi
|
|
129
|
+
rm "$READY_FILE" "$HOLDER_PID_FILE" "$INBOX_FIFO" "$RUNNER_INBOX_FIFO" 2>/dev/null || true
|
|
100
130
|
}
|
|
101
131
|
|
|
102
132
|
prepare_live_mailbox() {
|
|
103
133
|
local path old_umask rc=0
|
|
104
|
-
for path in "$INBOX_FIFO" "$
|
|
134
|
+
for path in "$INBOX_FIFO" "$RUNNER_INBOX_FIFO" "$HOLDER_PID_FILE" \
|
|
135
|
+
"$READY_FILE" "$EVENTS_FILE" "$EVENTS_ALIAS"; do
|
|
105
136
|
[[ ! -e "$path" && ! -L "$path" ]] || return 1
|
|
106
137
|
done
|
|
107
138
|
old_umask="$(umask)"
|
|
108
139
|
umask 077
|
|
109
|
-
mkfifo "$INBOX_FIFO" || rc=$?
|
|
140
|
+
mkfifo "$INBOX_FIFO" "$RUNNER_INBOX_FIFO" || rc=$?
|
|
110
141
|
if [[ "$rc" -eq 0 ]]; then
|
|
111
142
|
: > "$EVENTS_FILE" || rc=$?
|
|
112
143
|
fi
|
|
@@ -114,31 +145,38 @@ prepare_live_mailbox() {
|
|
|
114
145
|
ln "$EVENTS_FILE" "$EVENTS_ALIAS" || rc=$?
|
|
115
146
|
fi
|
|
116
147
|
if [[ "$rc" -eq 0 ]]; then
|
|
117
|
-
chmod 600 "$INBOX_FIFO" "$EVENTS_FILE" "$EVENTS_ALIAS" || rc=$?
|
|
148
|
+
chmod 600 "$INBOX_FIFO" "$RUNNER_INBOX_FIFO" "$EVENTS_FILE" "$EVENTS_ALIAS" || rc=$?
|
|
118
149
|
fi
|
|
119
150
|
umask "$old_umask"
|
|
120
151
|
if [[ "$rc" -ne 0 ]]; then
|
|
121
|
-
rm "$EVENTS_ALIAS" "$EVENTS_FILE" "$INBOX_FIFO" 2>/dev/null || true
|
|
152
|
+
rm "$EVENTS_ALIAS" "$EVENTS_FILE" "$INBOX_FIFO" "$RUNNER_INBOX_FIFO" 2>/dev/null || true
|
|
122
153
|
fi
|
|
123
154
|
return "$rc"
|
|
124
155
|
}
|
|
125
156
|
|
|
126
157
|
last_result_status() {
|
|
127
|
-
local last_result
|
|
128
|
-
|
|
158
|
+
local event last_result=""
|
|
159
|
+
while IFS= read -r event || [[ -n "$event" ]]; do
|
|
160
|
+
if live_event_is_result "$VENDOR" "$event"; then last_result="$event"; fi
|
|
161
|
+
done < "$EVENTS_FILE"
|
|
129
162
|
[[ -n "$last_result" ]] || return 1
|
|
130
|
-
|
|
163
|
+
live_event_is_success "$VENDOR" "$last_result"
|
|
131
164
|
}
|
|
132
165
|
|
|
133
166
|
if ! prepare_live_mailbox; then
|
|
167
|
+
if [[ "$LIVE_REQUIRED" -eq 1 ]]; then
|
|
168
|
+
echo "omnilane: required $VENDOR live mailbox unavailable because FIFO setup failed" >&2
|
|
169
|
+
exit 1
|
|
170
|
+
fi
|
|
134
171
|
set +e
|
|
135
|
-
run_single_shot "omnilane:
|
|
172
|
+
run_single_shot "omnilane: $VENDOR live mailbox unavailable because FIFO setup failed; ran in single-shot mode"
|
|
136
173
|
rc=$?
|
|
137
174
|
set -e
|
|
138
175
|
exit "$rc"
|
|
139
176
|
fi
|
|
140
177
|
|
|
141
178
|
trap 'close_requested=1' USR1
|
|
179
|
+
trap 'close_requested=1' PIPE
|
|
142
180
|
trap cleanup_live_mailbox EXIT
|
|
143
181
|
truncate_payload "$PROMPT_FILE" 102400
|
|
144
182
|
INITIAL_TEXT="$(cat "$PROMPT_FILE")"
|
|
@@ -149,44 +187,67 @@ else
|
|
|
149
187
|
fi
|
|
150
188
|
|
|
151
189
|
write_current_pid_file "$HOLDER_PID_FILE"
|
|
152
|
-
export OMNILANE_INBOX="$
|
|
190
|
+
export OMNILANE_INBOX="$RUNNER_INBOX_FIFO"
|
|
153
191
|
"$RUNNER" "$MODE" "$WORKDIR" "$MODEL" "$EFFORT" "$PROMPT_FILE" "$OUTPUT_FILE" &
|
|
154
192
|
runner_pid=$!
|
|
155
193
|
|
|
156
|
-
# Open only after
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
fi
|
|
194
|
+
# Open the runner writer only after its FIFO reader starts.
|
|
195
|
+
exec 3> "$RUNNER_INBOX_FIFO"
|
|
196
|
+
runner_writer_open=1
|
|
197
|
+
exec 4<> "$INBOX_FIFO"
|
|
198
|
+
inbox_open=1
|
|
199
|
+
exec 5< "$EVENTS_FILE"
|
|
200
|
+
events_reader_open=1
|
|
201
|
+
initial_payload="$(live_encode_message "$VENDOR" "$JOB_ID" "$FOREMAN_SESSION_VALUE" "$INITIAL_TEXT")"
|
|
202
|
+
if ! printf '%s\n' "$initial_payload" >&3; then close_requested=1; fi
|
|
165
203
|
(umask 077; : > "$READY_FILE")
|
|
166
204
|
|
|
205
|
+
last_activity=$SECONDS
|
|
206
|
+
while kill -0 "$runner_pid" 2>/dev/null; do
|
|
207
|
+
[[ "$close_requested" -eq 0 ]] || break
|
|
208
|
+
incoming=""
|
|
209
|
+
if IFS= read -r -t 1 incoming <&4; then
|
|
210
|
+
if ! printf '%s\n' "$incoming" >&3; then close_requested=1; fi
|
|
211
|
+
last_activity=$SECONDS
|
|
212
|
+
fi
|
|
213
|
+
while IFS= read -r event <&5; do
|
|
214
|
+
if live_event_is_result "$VENDOR" "$event"; then
|
|
215
|
+
last_activity=$SECONDS
|
|
216
|
+
fi
|
|
217
|
+
done
|
|
218
|
+
if [[ "$IDLE_TIMEOUT" -gt 0 && $((SECONDS - last_activity)) -ge "$IDLE_TIMEOUT" ]]; then
|
|
219
|
+
close_reason="closed by idle cap after ${IDLE_TIMEOUT}s"
|
|
220
|
+
close_requested=1
|
|
221
|
+
fi
|
|
222
|
+
done
|
|
223
|
+
|
|
224
|
+
if [[ "$runner_writer_open" -eq 1 ]]; then exec 3>&-; runner_writer_open=0; fi
|
|
225
|
+
if [[ "$inbox_open" -eq 1 ]]; then exec 4>&-; inbox_open=0; fi
|
|
226
|
+
if [[ "$events_reader_open" -eq 1 ]]; then exec 5<&-; events_reader_open=0; fi
|
|
227
|
+
|
|
167
228
|
set +e
|
|
168
|
-
|
|
229
|
+
if [[ "$close_requested" -eq 1 ]]; then
|
|
230
|
+
kill -TERM "$runner_pid" 2>/dev/null || true
|
|
231
|
+
fi
|
|
232
|
+
wait "$runner_pid" 2>/dev/null
|
|
169
233
|
runner_rc=$?
|
|
170
234
|
set -e
|
|
171
235
|
|
|
236
|
+
if [[ -n "$close_reason" ]]; then
|
|
237
|
+
printf '\n%s\n' "$close_reason" >> "$OUTPUT_FILE"
|
|
238
|
+
emit_mode_notice "$close_reason" || true
|
|
239
|
+
fi
|
|
240
|
+
|
|
172
241
|
if [[ "$close_requested" -eq 1 ]]; then
|
|
173
|
-
exec 3>&-
|
|
174
|
-
inbox_holder_open=0
|
|
175
|
-
set +e
|
|
176
|
-
kill -TERM "$runner_pid" 2>/dev/null || true
|
|
177
|
-
wait "$runner_pid" 2>/dev/null
|
|
178
|
-
set -e
|
|
179
242
|
if last_result_status; then
|
|
180
243
|
rc=0
|
|
181
244
|
else
|
|
182
245
|
rc=1
|
|
183
|
-
emit_mode_notice "omnilane:
|
|
246
|
+
emit_mode_notice "omnilane: $VENDOR live mailbox closed without a successful result event" || true
|
|
184
247
|
fi
|
|
185
248
|
else
|
|
186
|
-
exec 3>&-
|
|
187
|
-
inbox_holder_open=0
|
|
188
249
|
rc="$runner_rc"
|
|
189
250
|
fi
|
|
190
251
|
|
|
191
|
-
trap - USR1
|
|
252
|
+
trap - USR1 PIPE
|
|
192
253
|
exit "$rc"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Shared live-mailbox protocol differences. Callers provide json_escape().
|
|
4
|
+
|
|
5
|
+
live_capable_vendors() {
|
|
6
|
+
printf 'claude, gemini'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
live_vendor_capable() {
|
|
10
|
+
case "$1" in
|
|
11
|
+
claude|gemini) return 0 ;;
|
|
12
|
+
*) return 1 ;;
|
|
13
|
+
esac
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
live_encode_message() {
|
|
17
|
+
local vendor="$1" job_id="$2" foreman_session="$3" text="$4"
|
|
18
|
+
case "$vendor" in
|
|
19
|
+
claude)
|
|
20
|
+
printf '{"type":"user","omnilane_job_id":"%s","foreman_session":"%s","message":{"role":"user","content":[{"type":"text","text":"%s"}]}}' \
|
|
21
|
+
"$(json_escape "$job_id")" "$(json_escape "$foreman_session")" \
|
|
22
|
+
"$(json_escape "$text")"
|
|
23
|
+
;;
|
|
24
|
+
gemini)
|
|
25
|
+
printf '{"event":"user","message":{"role":"user","content":[{"type":"text","text":"%s"}]}}' \
|
|
26
|
+
"$(json_escape "$text")"
|
|
27
|
+
;;
|
|
28
|
+
*) return 2 ;;
|
|
29
|
+
esac
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
live_event_is_result() {
|
|
33
|
+
local vendor="$1" event="$2" pattern
|
|
34
|
+
case "$vendor" in
|
|
35
|
+
claude) pattern='"type"[[:space:]]*:[[:space:]]*"result"' ;;
|
|
36
|
+
gemini) pattern='"event"[[:space:]]*:[[:space:]]*"result"' ;;
|
|
37
|
+
*) return 2 ;;
|
|
38
|
+
esac
|
|
39
|
+
[[ "$event" =~ $pattern ]]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
live_event_is_success() {
|
|
43
|
+
local vendor="$1" event="$2" pattern
|
|
44
|
+
live_event_is_result "$vendor" "$event" || return 1
|
|
45
|
+
case "$vendor" in
|
|
46
|
+
claude)
|
|
47
|
+
pattern='"is_error"[[:space:]]*:[[:space:]]*true'
|
|
48
|
+
[[ ! "$event" =~ $pattern ]]
|
|
49
|
+
;;
|
|
50
|
+
gemini)
|
|
51
|
+
pattern='"status"[[:space:]]*:[[:space:]]*"SUCCESS"'
|
|
52
|
+
[[ "$event" =~ $pattern ]]
|
|
53
|
+
;;
|
|
54
|
+
*) return 2 ;;
|
|
55
|
+
esac
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
live_count_result_events() {
|
|
59
|
+
local vendor="$1" path="$2" event count=0
|
|
60
|
+
[[ -f "$path" && ! -L "$path" ]] || {
|
|
61
|
+
printf '0'
|
|
62
|
+
return 0
|
|
63
|
+
}
|
|
64
|
+
while IFS= read -r event || [[ -n "$event" ]]; do
|
|
65
|
+
if live_event_is_result "$vendor" "$event"; then
|
|
66
|
+
count=$((count + 1))
|
|
67
|
+
fi
|
|
68
|
+
done < "$path"
|
|
69
|
+
printf '%s' "$count"
|
|
70
|
+
}
|
|
@@ -33,6 +33,115 @@ MODEL_ARGS=()
|
|
|
33
33
|
# plan = read-only tools (advise), accept-edits = file edits allowed (work).
|
|
34
34
|
if [[ "$MODE" == "advise" ]]; then MODE_ARGS=(--mode plan); else MODE_ARGS=(--mode accept-edits); fi
|
|
35
35
|
|
|
36
|
+
LIVE_INBOX="${OMNILANE_INBOX:-}"
|
|
37
|
+
if [[ -n "$LIVE_INBOX" && -p "$LIVE_INBOX" ]]; then
|
|
38
|
+
EVENTS_FILE="${OUTPUT_FILE}.events.jsonl"
|
|
39
|
+
STDERR_FILE="${OUTPUT_FILE}.stderr.log"
|
|
40
|
+
LIVE_CHILD_PID=""
|
|
41
|
+
|
|
42
|
+
if [[ -L "$EVENTS_FILE" || ( -e "$EVENTS_FILE" && ! -f "$EVENTS_FILE" ) ]]; then
|
|
43
|
+
echo "omnilane: unsafe Gemini live event path" >&2
|
|
44
|
+
exit 125
|
|
45
|
+
fi
|
|
46
|
+
(umask 077; : > "$EVENTS_FILE"; : > "$STDERR_FILE")
|
|
47
|
+
|
|
48
|
+
finalize_live_output() {
|
|
49
|
+
local tmp="${OUTPUT_FILE}.tmp"
|
|
50
|
+
if ! command -v python3 >/dev/null 2>&1; then
|
|
51
|
+
echo "omnilane: cannot extract Gemini live result: python3 not found" >> "$STDERR_FILE"
|
|
52
|
+
return 1
|
|
53
|
+
fi
|
|
54
|
+
if ! python3 - "$EVENTS_FILE" "$tmp" <<'PY'
|
|
55
|
+
import json
|
|
56
|
+
import pathlib
|
|
57
|
+
import sys
|
|
58
|
+
|
|
59
|
+
events_path = pathlib.Path(sys.argv[1])
|
|
60
|
+
output_path = pathlib.Path(sys.argv[2])
|
|
61
|
+
last_response = None
|
|
62
|
+
|
|
63
|
+
with events_path.open(encoding="utf-8") as events:
|
|
64
|
+
for raw_line in events:
|
|
65
|
+
try:
|
|
66
|
+
event = json.loads(raw_line)
|
|
67
|
+
except json.JSONDecodeError:
|
|
68
|
+
continue
|
|
69
|
+
result = event.get("result")
|
|
70
|
+
if (
|
|
71
|
+
event.get("event") == "result"
|
|
72
|
+
and isinstance(result, dict)
|
|
73
|
+
and result.get("status") == "SUCCESS"
|
|
74
|
+
and isinstance(result.get("response"), str)
|
|
75
|
+
):
|
|
76
|
+
last_response = result["response"]
|
|
77
|
+
|
|
78
|
+
if last_response is None:
|
|
79
|
+
raise SystemExit(1)
|
|
80
|
+
|
|
81
|
+
output_path.write_text(last_response.rstrip("\n") + "\n", encoding="utf-8")
|
|
82
|
+
PY
|
|
83
|
+
then
|
|
84
|
+
echo "omnilane: Gemini live stream ended without a readable SUCCESS result" >> "$STDERR_FILE"
|
|
85
|
+
return 1
|
|
86
|
+
fi
|
|
87
|
+
mv "$tmp" "$OUTPUT_FILE"
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Invoked by signal traps below.
|
|
91
|
+
# shellcheck disable=SC2329
|
|
92
|
+
stop_live_child() {
|
|
93
|
+
local signal_rc="$1" waited=0
|
|
94
|
+
trap - TERM HUP INT
|
|
95
|
+
set +e
|
|
96
|
+
if [[ -n "$LIVE_CHILD_PID" ]] && kill -0 "$LIVE_CHILD_PID" 2>/dev/null; then
|
|
97
|
+
kill -TERM "-$LIVE_CHILD_PID" 2>/dev/null || kill -TERM "$LIVE_CHILD_PID" 2>/dev/null || true
|
|
98
|
+
while kill -0 "$LIVE_CHILD_PID" 2>/dev/null && [[ "$waited" -lt 50 ]]; do
|
|
99
|
+
sleep 0.1
|
|
100
|
+
waited=$((waited + 1))
|
|
101
|
+
done
|
|
102
|
+
if kill -0 "$LIVE_CHILD_PID" 2>/dev/null; then
|
|
103
|
+
kill -KILL "-$LIVE_CHILD_PID" 2>/dev/null || kill -KILL "$LIVE_CHILD_PID" 2>/dev/null || true
|
|
104
|
+
fi
|
|
105
|
+
wait "$LIVE_CHILD_PID" 2>/dev/null
|
|
106
|
+
fi
|
|
107
|
+
finalize_live_output || true
|
|
108
|
+
[[ -s "$STDERR_FILE" ]] || rm "$STDERR_FILE" 2>/dev/null || true
|
|
109
|
+
exit "$signal_rc"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
set -m
|
|
113
|
+
(
|
|
114
|
+
cd "$RUN_DIR" || exit 127
|
|
115
|
+
run_with_timeout "$RUN_TIMEOUT" env \
|
|
116
|
+
-u GEMINI_API_KEY -u GOOGLE_API_KEY -u GOOGLE_AI_API_KEY \
|
|
117
|
+
NO_BROWSER=1 OMNILANE_DEPTH=1 \
|
|
118
|
+
"$AGY_BIN" --dangerously-skip-permissions --add-dir "$RUN_DIR" \
|
|
119
|
+
"${MODE_ARGS[@]}" ${MODEL_ARGS[@]+"${MODEL_ARGS[@]}"} \
|
|
120
|
+
--input-format stream-json --output-format stream-json -p "" \
|
|
121
|
+
< "$LIVE_INBOX" > "$EVENTS_FILE" 2> "$STDERR_FILE"
|
|
122
|
+
) &
|
|
123
|
+
LIVE_CHILD_PID=$!
|
|
124
|
+
set +m
|
|
125
|
+
trap 'stop_live_child 143' TERM
|
|
126
|
+
trap 'stop_live_child 129' HUP
|
|
127
|
+
trap 'stop_live_child 130' INT
|
|
128
|
+
|
|
129
|
+
set +e
|
|
130
|
+
wait "$LIVE_CHILD_PID"
|
|
131
|
+
RC=$?
|
|
132
|
+
set -e
|
|
133
|
+
trap - TERM HUP INT
|
|
134
|
+
if ! finalize_live_output && [[ "$RC" -eq 0 ]]; then
|
|
135
|
+
RC=1
|
|
136
|
+
fi
|
|
137
|
+
if grep -Eiq "$CAPACITY_PATTERN" "$EVENTS_FILE" "$STDERR_FILE" 2>/dev/null; then
|
|
138
|
+
echo "omnilane: gemini capacity exhausted" >> "$STDERR_FILE"
|
|
139
|
+
RC=126
|
|
140
|
+
fi
|
|
141
|
+
[[ -s "$STDERR_FILE" ]] || rm "$STDERR_FILE" 2>/dev/null || true
|
|
142
|
+
exit "$RC"
|
|
143
|
+
fi
|
|
144
|
+
|
|
36
145
|
set +e
|
|
37
146
|
(
|
|
38
147
|
cd "$RUN_DIR" || exit 127
|