提交一次代码
This commit is contained in:
345
scripts/superagent-direct-stream-test.sh
Executable file
345
scripts/superagent-direct-stream-test.sh
Executable file
@@ -0,0 +1,345 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
# Direct SuperAgent Open API stream test.
|
||||
# Purpose: bypass TH Hotel backend Debug EML / OSS / SourceMessage and test
|
||||
# whether SuperAgent Open API itself times out or returns usable SSE events.
|
||||
#
|
||||
# Usage on test server:
|
||||
# cd /home/th-hotel-simple
|
||||
# bash ./superagent-direct-stream-test.sh
|
||||
#
|
||||
# You can either edit the variables below, or override them before running:
|
||||
# ENV_FILE=/home/th-hotel-simple/th-hotel-server.env bash ./superagent-direct-stream-test.sh
|
||||
|
||||
#######################################
|
||||
# Editable parameters
|
||||
#######################################
|
||||
|
||||
# Your test server env file. It can be plain key=value format.
|
||||
ENV_FILE="${ENV_FILE:-/home/th-hotel-simple/th-hotel-server.env}"
|
||||
|
||||
# Output directory for generated request bodies, response headers, and SSE body.
|
||||
OUTPUT_DIR="${OUTPUT_DIR:-/tmp/th-hotel-superagent-direct}"
|
||||
|
||||
# Curl timeout. This is total curl max time, not SuperAgent's own timeout.
|
||||
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-1900}"
|
||||
CONNECT_TIMEOUT_SECONDS="${CONNECT_TIMEOUT_SECONDS:-30}"
|
||||
|
||||
# Optional hard overrides. Leave empty to read from ENV_FILE variables.
|
||||
BASE_URL="${BASE_URL:-}"
|
||||
API_KEY="${API_KEY:-}"
|
||||
EXTERNAL_SUBJECT_ID="${EXTERNAL_SUBJECT_ID:-}"
|
||||
|
||||
# The direct test message. Keep it simple first; switch MESSAGE_PAYLOAD_FILE to
|
||||
# a larger JSON later if you want to mimic Debug EML more closely. If you only
|
||||
# have an .eml file, set EML_FILE and the script will embed the raw EML text in
|
||||
# the message payload JSON.
|
||||
MESSAGE_SUBJECT="${MESSAGE_SUBJECT:-timeout test}"
|
||||
MESSAGE_TEXT="${MESSAGE_TEXT:-This is a direct curl timeout test. Please return a JSON result.}"
|
||||
MESSAGE_PAYLOAD_FILE="${MESSAGE_PAYLOAD_FILE:-}"
|
||||
EML_FILE="${EML_FILE:-}"
|
||||
MESSAGE_PREFIX="${MESSAGE_PREFIX:-请基于以下 Debug 邮件 JSON 输出结构化任务抽取结果,只返回 JSON,不要创建订单或任务:}"
|
||||
|
||||
#######################################
|
||||
# Helpers
|
||||
#######################################
|
||||
|
||||
require_command() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
echo "Missing required command: $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
mask_secret() {
|
||||
local value="${1:-}"
|
||||
if [ -z "$value" ]; then
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
if [ "${#value}" -le 8 ]; then
|
||||
echo "****"
|
||||
return
|
||||
fi
|
||||
echo "${value:0:4}****${value: -4}"
|
||||
}
|
||||
|
||||
load_env_file() {
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "ENV_FILE not found: $ENV_FILE" >&2
|
||||
echo "Edit ENV_FILE at the top of this script, or pass ENV_FILE=/path/to/file." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC1090
|
||||
set -a
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
}
|
||||
|
||||
normalize_config() {
|
||||
BASE_URL="${BASE_URL:-${DEERFLOW_TEST_BASE_URL:-${DEERFLOW_BASE_URL:-}}}"
|
||||
API_KEY="${API_KEY:-${DEERFLOW_TEST_OPEN_API_KEY:-${DEERFLOW_OPEN_API_KEY:-}}}"
|
||||
if [ -z "$EXTERNAL_SUBJECT_ID" ]; then
|
||||
EXTERNAL_SUBJECT_ID="${SUPERAGENT_TEST_DEBUG_EML_EXTERNAL_SUBJECT_ID:-${SUPERAGENT_DEBUG_EML_EXTERNAL_SUBJECT_ID:-th-hotel-debug-eml-upload}}"
|
||||
fi
|
||||
|
||||
if [ -z "$BASE_URL" ]; then
|
||||
echo "BASE_URL is empty. Set DEERFLOW_TEST_BASE_URL / DEERFLOW_BASE_URL or edit BASE_URL." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$API_KEY" ]; then
|
||||
echo "API_KEY is empty. Set DEERFLOW_TEST_OPEN_API_KEY / DEERFLOW_OPEN_API_KEY or edit API_KEY." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$EXTERNAL_SUBJECT_ID" ]; then
|
||||
echo "EXTERNAL_SUBJECT_ID is empty. Set SUPERAGENT_TEST_DEBUG_EML_EXTERNAL_SUBJECT_ID or edit it." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$MESSAGE_PAYLOAD_FILE" ] && [ ! -f "$MESSAGE_PAYLOAD_FILE" ]; then
|
||||
echo "MESSAGE_PAYLOAD_FILE not found: $MESSAGE_PAYLOAD_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$EML_FILE" ] && [ ! -f "$EML_FILE" ]; then
|
||||
echo "EML_FILE not found: $EML_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BASE_URL="${BASE_URL%/}"
|
||||
}
|
||||
|
||||
print_config() {
|
||||
echo "=== Direct SuperAgent stream test ==="
|
||||
echo "ENV_FILE=$ENV_FILE"
|
||||
echo "OUTPUT_DIR=$OUTPUT_DIR"
|
||||
echo "BASE_URL=$BASE_URL"
|
||||
echo "EXTERNAL_SUBJECT_ID=$EXTERNAL_SUBJECT_ID"
|
||||
echo "API_KEY=$(mask_secret "$API_KEY")"
|
||||
echo "TIMEOUT_SECONDS=$TIMEOUT_SECONDS"
|
||||
echo "CONNECT_TIMEOUT_SECONDS=$CONNECT_TIMEOUT_SECONDS"
|
||||
echo "MESSAGE_SUBJECT=$MESSAGE_SUBJECT"
|
||||
if [ -n "$MESSAGE_PAYLOAD_FILE" ]; then
|
||||
echo "MESSAGE_PAYLOAD_FILE=$MESSAGE_PAYLOAD_FILE"
|
||||
fi
|
||||
if [ -n "$EML_FILE" ]; then
|
||||
echo "EML_FILE=$EML_FILE"
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
write_create_body() {
|
||||
python3 - <<'PY' > "$CREATE_BODY"
|
||||
import json
|
||||
import os
|
||||
|
||||
run_id = os.environ["RUN_ID"]
|
||||
subject = os.environ["EXTERNAL_SUBJECT_ID"]
|
||||
|
||||
print(json.dumps({
|
||||
"external_subject_id": subject,
|
||||
"idempotency_key": f"{run_id}-session",
|
||||
"metadata": {
|
||||
"source": "direct-curl",
|
||||
"debug_run_id": run_id
|
||||
}
|
||||
}, ensure_ascii=False))
|
||||
PY
|
||||
}
|
||||
|
||||
write_stream_body() {
|
||||
python3 - <<'PY' > "$STREAM_BODY"
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
run_id = os.environ["RUN_ID"]
|
||||
payload_file = os.environ.get("MESSAGE_PAYLOAD_FILE", "").strip()
|
||||
eml_file = os.environ.get("EML_FILE", "").strip()
|
||||
prefix = os.environ["MESSAGE_PREFIX"]
|
||||
|
||||
if payload_file:
|
||||
payload_text = Path(payload_file).read_text(encoding="utf-8")
|
||||
elif eml_file:
|
||||
eml_path = Path(eml_file)
|
||||
raw_eml = eml_path.read_text(encoding="utf-8", errors="replace")
|
||||
payload_text = json.dumps({
|
||||
"source": "direct-curl",
|
||||
"schema_version": "direct-raw-eml-v1",
|
||||
"raw_eml_file_name": eml_path.name,
|
||||
"raw_eml_size_bytes": eml_path.stat().st_size,
|
||||
"raw_eml": raw_eml,
|
||||
}, ensure_ascii=False)
|
||||
else:
|
||||
payload_text = json.dumps({
|
||||
"source": "direct-curl",
|
||||
"subject": os.environ["MESSAGE_SUBJECT"],
|
||||
"text": os.environ["MESSAGE_TEXT"],
|
||||
}, ensure_ascii=False)
|
||||
|
||||
message = prefix + "\n" + payload_text
|
||||
|
||||
print(json.dumps({
|
||||
"message": message,
|
||||
"idempotency_key": f"{run_id}-message",
|
||||
"metadata": {
|
||||
"source": "direct-curl",
|
||||
"debug_run_id": run_id,
|
||||
"source_message_id": "direct-curl",
|
||||
"hotel_id": "DIRECT"
|
||||
}
|
||||
}, ensure_ascii=False))
|
||||
PY
|
||||
}
|
||||
|
||||
extract_session_id() {
|
||||
python3 - "$CREATE_RESPONSE" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
path = sys.argv[1]
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
except Exception:
|
||||
print("")
|
||||
raise SystemExit(0)
|
||||
|
||||
print(data.get("session_id") or data.get("id") or "")
|
||||
PY
|
||||
}
|
||||
|
||||
curl_create_session() {
|
||||
local csrf="$RUN_ID-create"
|
||||
echo "=== Creating SuperAgent session ==="
|
||||
|
||||
set +e
|
||||
CREATE_HTTP_CODE="$(
|
||||
curl -sS \
|
||||
--connect-timeout "$CONNECT_TIMEOUT_SECONDS" \
|
||||
--max-time "$TIMEOUT_SECONDS" \
|
||||
-w "%{http_code}" \
|
||||
-D "$CREATE_HEADERS" \
|
||||
-o "$CREATE_RESPONSE" \
|
||||
-X POST "$BASE_URL/api/open/agent-sessions" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-H "X-CSRF-Token: $csrf" \
|
||||
-H "Cookie: csrf_token=$csrf" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data-binary @"$CREATE_BODY"
|
||||
)"
|
||||
CREATE_CURL_EXIT=$?
|
||||
set -e
|
||||
|
||||
echo "create curl exit=$CREATE_CURL_EXIT http=$CREATE_HTTP_CODE"
|
||||
echo "create headers: $CREATE_HEADERS"
|
||||
echo "create response: $CREATE_RESPONSE"
|
||||
|
||||
if [ "$CREATE_CURL_EXIT" -ne 0 ] || [ "$CREATE_HTTP_CODE" -lt 200 ] || [ "$CREATE_HTTP_CODE" -ge 300 ]; then
|
||||
echo "Create session failed. Response body:" >&2
|
||||
cat "$CREATE_RESPONSE" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SESSION_ID="$(extract_session_id)"
|
||||
if [ -z "$SESSION_ID" ]; then
|
||||
echo "Create session response does not contain session_id or id. Body:" >&2
|
||||
cat "$CREATE_RESPONSE" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SESSION_ID=$SESSION_ID"
|
||||
echo
|
||||
}
|
||||
|
||||
curl_stream_message() {
|
||||
local csrf="$RUN_ID-message"
|
||||
echo "=== Calling SuperAgent message stream ==="
|
||||
echo "This may run for a long time. Output is saved to: $STREAM_RESPONSE"
|
||||
|
||||
local started_at ended_at elapsed
|
||||
started_at="$(date +%s)"
|
||||
|
||||
set +e
|
||||
STREAM_HTTP_CODE="$(
|
||||
curl -sS -N --no-buffer \
|
||||
--connect-timeout "$CONNECT_TIMEOUT_SECONDS" \
|
||||
--max-time "$TIMEOUT_SECONDS" \
|
||||
-w "%{http_code}" \
|
||||
-D "$STREAM_HEADERS" \
|
||||
-o "$STREAM_RESPONSE" \
|
||||
-X POST "$BASE_URL/api/open/agent-sessions/$SESSION_ID/messages/stream" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-H "X-CSRF-Token: $csrf" \
|
||||
-H "Cookie: csrf_token=$csrf" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: text/event-stream" \
|
||||
--data-binary @"$STREAM_BODY"
|
||||
)"
|
||||
STREAM_CURL_EXIT=$?
|
||||
set -e
|
||||
|
||||
ended_at="$(date +%s)"
|
||||
elapsed="$((ended_at - started_at))"
|
||||
|
||||
echo "stream curl exit=$STREAM_CURL_EXIT http=$STREAM_HTTP_CODE elapsed_seconds=$elapsed"
|
||||
echo "stream headers: $STREAM_HEADERS"
|
||||
echo "stream response: $STREAM_RESPONSE"
|
||||
echo
|
||||
}
|
||||
|
||||
summarize_stream() {
|
||||
echo "=== Stream headers ==="
|
||||
cat "$STREAM_HEADERS" || true
|
||||
echo
|
||||
|
||||
echo "=== Stream event summary ==="
|
||||
if [ -s "$STREAM_RESPONSE" ]; then
|
||||
grep -E '^event:' "$STREAM_RESPONSE" | sort | uniq -c || true
|
||||
echo
|
||||
echo "Last 120 lines:"
|
||||
tail -n 120 "$STREAM_RESPONSE" || true
|
||||
else
|
||||
echo "Stream response file is empty."
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Main
|
||||
#######################################
|
||||
|
||||
require_command curl
|
||||
require_command python3
|
||||
|
||||
load_env_file
|
||||
normalize_config
|
||||
|
||||
RUN_ID="${RUN_ID:-direct-curl-$(date +%Y%m%d-%H%M%S)}"
|
||||
export BASE_URL API_KEY EXTERNAL_SUBJECT_ID RUN_ID
|
||||
export MESSAGE_SUBJECT MESSAGE_TEXT MESSAGE_PAYLOAD_FILE EML_FILE MESSAGE_PREFIX
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
CREATE_BODY="$OUTPUT_DIR/$RUN_ID-create-body.json"
|
||||
CREATE_HEADERS="$OUTPUT_DIR/$RUN_ID-create.headers"
|
||||
CREATE_RESPONSE="$OUTPUT_DIR/$RUN_ID-create.json"
|
||||
STREAM_BODY="$OUTPUT_DIR/$RUN_ID-stream-body.json"
|
||||
STREAM_HEADERS="$OUTPUT_DIR/$RUN_ID-stream.headers"
|
||||
STREAM_RESPONSE="$OUTPUT_DIR/$RUN_ID-stream.sse"
|
||||
|
||||
export CREATE_BODY STREAM_BODY CREATE_RESPONSE
|
||||
|
||||
print_config
|
||||
write_create_body
|
||||
write_stream_body
|
||||
|
||||
echo "create request body: $CREATE_BODY"
|
||||
echo "stream request body: $STREAM_BODY"
|
||||
echo
|
||||
|
||||
curl_create_session
|
||||
curl_stream_message
|
||||
summarize_stream
|
||||
|
||||
echo "Done."
|
||||
Reference in New Issue
Block a user