@hybroai/cli 0.4.6 → 0.4.7
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/bin/hybro +74 -11
- package/package.json +1 -1
package/bin/hybro
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# package's bin, and the release asset that install.sh installs (release mode).
|
|
6
6
|
set -u
|
|
7
7
|
|
|
8
|
-
HYBRO_VERSION="0.4.
|
|
8
|
+
HYBRO_VERSION="0.4.7" # x-release-please-version
|
|
9
9
|
|
|
10
10
|
GITHUB_REPO="hybroai/hybro"
|
|
11
11
|
RELEASE_IMAGE="ghcr.io/hybroai/hybro"
|
|
@@ -78,7 +78,7 @@ Hybro $HYBRO_VERSION: AI agents and rooms in one container.
|
|
|
78
78
|
Usage: $CLI [command] [options]
|
|
79
79
|
|
|
80
80
|
Commands:
|
|
81
|
-
start Start Hybro and
|
|
81
|
+
start Start Hybro and show only its errors (the default command)
|
|
82
82
|
stop Stop Hybro
|
|
83
83
|
status Show whether Hybro is running and its address
|
|
84
84
|
logs Show Hybro's logs; docker logs options such as -f pass through
|
|
@@ -348,17 +348,62 @@ start_container() {
|
|
|
348
348
|
die "cannot start the $CONTAINER container"
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
READY_TIMEOUT=180
|
|
352
|
+
# Any HTTP answer counts, as /health answers 503 while a dependency is degraded.
|
|
353
|
+
# The backend and the frontend first: Caddy logs an error for each request it
|
|
354
|
+
# cannot proxy.
|
|
355
|
+
HEALTH_PROBE='import http.client
|
|
356
|
+
for port, path in ((8000, "/health"), (3000, "/"), (8080, "/health")):
|
|
357
|
+
connection = http.client.HTTPConnection("127.0.0.1", port, timeout=2)
|
|
358
|
+
connection.request("GET", path)
|
|
359
|
+
connection.getresponse()'
|
|
360
|
+
|
|
361
|
+
# Waits until the backend, the frontend and Caddy answer; fails on Ctrl-C,
|
|
362
|
+
# when the container stops, or when the timeout passes.
|
|
363
|
+
wait_ready() {
|
|
364
|
+
started=$(date +%s)
|
|
365
|
+
while :; do
|
|
366
|
+
[ "$INTERRUPTED" = 0 ] || return 1
|
|
367
|
+
[ "$(container_state)" = running ] || return 1
|
|
368
|
+
docker exec "$CONTAINER" "$DIAG_PYTHON" -c "$HEALTH_PROBE" >/dev/null 2>&1 && break
|
|
369
|
+
[ $(($(date +%s) - started)) -lt "$READY_TIMEOUT" ] || return 1
|
|
370
|
+
sleep 1
|
|
371
|
+
done
|
|
372
|
+
[ "$INTERRUPTED" = 0 ] || return 1
|
|
373
|
+
READY_SECONDS=$(($(date +%s) - started))
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
stop_on_interrupt() {
|
|
377
|
+
[ "$INTERRUPTED" = 1 ] || return 0
|
|
378
|
+
say "Stopping Hybro..."
|
|
379
|
+
docker stop "$CONTAINER" >/dev/null || die "cannot stop $CONTAINER"
|
|
380
|
+
exit 0
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
# The foreground start: a ready line, then only errors, including those logged
|
|
384
|
+
# while starting; mongod, Caddy and the agents warn on every normal start.
|
|
385
|
+
# supervisord lines carry no program name and are always shown. Ctrl-C stops
|
|
386
|
+
# Hybro.
|
|
351
387
|
follow_logs() {
|
|
352
|
-
say "
|
|
388
|
+
say "Starting Hybro $HYBRO_VERSION..."
|
|
353
389
|
INTERRUPTED=0
|
|
354
390
|
trap 'INTERRUPTED=1' INT
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
391
|
+
if ! wait_ready; then
|
|
392
|
+
trap - INT
|
|
393
|
+
stop_on_interrupt
|
|
394
|
+
docker logs --tail 30 "$CONTAINER" 2>&1
|
|
395
|
+
if [ "$(container_state)" = running ]; then
|
|
396
|
+
err "Hybro did not become ready within ${READY_TIMEOUT}s; it is still running."
|
|
397
|
+
die "Follow its logs with: $CLI logs -f, or stop it with: $CLI stop"
|
|
398
|
+
fi
|
|
399
|
+
code=$(docker container inspect -f '{{.State.ExitCode}}' "$CONTAINER" 2>/dev/null)
|
|
400
|
+
die "Hybro stopped before it was ready (exit code ${code:-unknown}). Show the logs with: $CLI logs"
|
|
361
401
|
fi
|
|
402
|
+
say "Hybro is ready at $url (${READY_SECONDS}s). Press Ctrl-C to stop."
|
|
403
|
+
say "Full logs: $CLI logs -f"
|
|
404
|
+
docker logs -f "$CONTAINER" 2>&1 | filter_logs "" "$(log_levels error)" ""
|
|
405
|
+
trap - INT
|
|
406
|
+
stop_on_interrupt
|
|
362
407
|
code=$(docker container inspect -f '{{.State.ExitCode}}' "$CONTAINER" 2>/dev/null)
|
|
363
408
|
die "Hybro stopped (exit code ${code:-unknown}). Show the logs with: $CLI logs"
|
|
364
409
|
}
|
|
@@ -453,8 +498,8 @@ cmd_start() {
|
|
|
453
498
|
ensure_image
|
|
454
499
|
start_container
|
|
455
500
|
url=$(url_for "$BIND" "$PORT")
|
|
456
|
-
say "Hybro is starting at $url"
|
|
457
501
|
if [ "$DETACH" = 1 ]; then
|
|
502
|
+
say "Hybro is starting at $url"
|
|
458
503
|
say "Running in the background. Stop it with: $CLI stop"
|
|
459
504
|
return 0
|
|
460
505
|
fi
|
|
@@ -547,7 +592,13 @@ cmd_logs() {
|
|
|
547
592
|
# docker's own errors carry no program prefix and are always shown; its exit
|
|
548
593
|
# status reaches awk as a sentinel line so a failure is not masked by the pipe.
|
|
549
594
|
{ docker logs "$@" "$CONTAINER" 2>&1 || echo "hybro_docker_exit=$?"; } |
|
|
550
|
-
|
|
595
|
+
filter_logs "$service" "$levels" "$trace"
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
# filter_logs <service> <level alternation> <trace id>: filters docker logs
|
|
599
|
+
# lines on stdin. A hybro_docker_exit=<n> line sets the exit status.
|
|
600
|
+
filter_logs() {
|
|
601
|
+
awk -v service="$1" -v levels="$2" -v trace="$3" '
|
|
551
602
|
/^hybro_docker_exit=[0-9]+$/ { code = substr($0, 19) + 0; next }
|
|
552
603
|
{
|
|
553
604
|
split_at = index($0, " | ")
|
|
@@ -564,7 +615,19 @@ cmd_logs() {
|
|
|
564
615
|
}
|
|
565
616
|
# JSON lines write level before any message text; logfmt lines start
|
|
566
617
|
# with it or with timestamp then level. Plain text has no level.
|
|
618
|
+
# mongod writes its severity as "s": F, E, W, I, or D1 to D5.
|
|
567
619
|
function level_of(text, value) {
|
|
620
|
+
if (match(text, /^[{]"t":[{][^}]*[}],"s":"[^"]*"/)) {
|
|
621
|
+
value = substr(text, RSTART, RLENGTH)
|
|
622
|
+
sub(/^.*"s":"/, "", value)
|
|
623
|
+
sub(/"$/, "", value)
|
|
624
|
+
if (value == "F") return "fatal"
|
|
625
|
+
if (value == "E") return "error"
|
|
626
|
+
if (value == "W") return "warning"
|
|
627
|
+
if (value == "I") return "info"
|
|
628
|
+
if (value ~ /^D[1-5]$/) return "debug"
|
|
629
|
+
return ""
|
|
630
|
+
}
|
|
568
631
|
if (substr(text, 1, 1) == "{") {
|
|
569
632
|
if (!match(text, /"level":"[^"]*"/)) return ""
|
|
570
633
|
return substr(text, RSTART + 9, RLENGTH - 10)
|