mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
fix: preserve codex include fields
This commit is contained in:
@@ -3,10 +3,9 @@ pub(crate) use aether_ai_formats::api::{
|
|||||||
aggregate_openai_chat_stream_sync_response, aggregate_openai_responses_stream_sync_response,
|
aggregate_openai_chat_stream_sync_response, aggregate_openai_responses_stream_sync_response,
|
||||||
aggregate_standard_chat_stream_sync_response, aggregate_standard_cli_stream_sync_response,
|
aggregate_standard_chat_stream_sync_response, aggregate_standard_cli_stream_sync_response,
|
||||||
api_format_alias_matches, api_format_storage_aliases,
|
api_format_alias_matches, api_format_storage_aliases,
|
||||||
apply_codex_openai_responses_chat_body_edits,
|
apply_codex_openai_responses_chat_body_edits, apply_codex_openai_responses_special_body_edits,
|
||||||
apply_codex_openai_responses_special_body_edits, apply_codex_openai_responses_special_headers,
|
apply_codex_openai_responses_special_headers, apply_model_directive_mapping_patch,
|
||||||
apply_model_directive_mapping_patch, apply_model_directive_overrides_from_model,
|
apply_model_directive_overrides_from_model, apply_model_directive_overrides_from_request,
|
||||||
apply_model_directive_overrides_from_request,
|
|
||||||
apply_openai_responses_compact_special_body_edits, build_chatgpt_web_image_request_body,
|
apply_openai_responses_compact_special_body_edits, build_chatgpt_web_image_request_body,
|
||||||
build_core_error_body_for_client_format, build_cross_format_openai_chat_request_body,
|
build_core_error_body_for_client_format, build_cross_format_openai_chat_request_body,
|
||||||
build_cross_format_openai_chat_request_body_with_model_directives,
|
build_cross_format_openai_chat_request_body_with_model_directives,
|
||||||
|
|||||||
@@ -300,14 +300,28 @@ fn ensure_codex_responses_passthrough_fields(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !body_rules_handle_path(body_rules, "parallel_tool_calls") {
|
if !body_rules_handle_path(body_rules, "parallel_tool_calls") {
|
||||||
body_object.insert("parallel_tool_calls".to_string(), json!(true));
|
body_object
|
||||||
|
.entry("parallel_tool_calls".to_string())
|
||||||
|
.or_insert_with(|| json!(true));
|
||||||
}
|
}
|
||||||
if !body_rules_handle_path(body_rules, "include") {
|
if !body_rules_handle_path(body_rules, "include") {
|
||||||
|
match body_object.get_mut("include") {
|
||||||
|
Some(Value::Array(include)) => {
|
||||||
|
let has_reasoning_encrypted_content = include
|
||||||
|
.iter()
|
||||||
|
.any(|value| value.as_str() == Some(CODEX_REASONING_ENCRYPTED_CONTENT_INCLUDE));
|
||||||
|
if !has_reasoning_encrypted_content {
|
||||||
|
include.push(json!(CODEX_REASONING_ENCRYPTED_CONTENT_INCLUDE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(_) | None => {
|
||||||
body_object.insert(
|
body_object.insert(
|
||||||
"include".to_string(),
|
"include".to_string(),
|
||||||
json!([CODEX_REASONING_ENCRYPTED_CONTENT_INCLUDE]),
|
json!([CODEX_REASONING_ENCRYPTED_CONTENT_INCLUDE]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_codex_chat_reasoning_defaults(
|
fn ensure_codex_chat_reasoning_defaults(
|
||||||
@@ -378,7 +392,7 @@ pub fn apply_codex_openai_responses_special_body_edits(
|
|||||||
json!(CODEX_DEFAULT_INSTRUCTIONS),
|
json!(CODEX_DEFAULT_INSTRUCTIONS),
|
||||||
);
|
);
|
||||||
} else if body_object.contains_key("instructions")
|
} else if body_object.contains_key("instructions")
|
||||||
&& body_object.get("instructions").map_or(false, |v| v.is_null())
|
&& body_object.get("instructions").is_some_and(|v| v.is_null())
|
||||||
{
|
{
|
||||||
body_object.insert("instructions".to_string(), json!(""));
|
body_object.insert("instructions".to_string(), json!(""));
|
||||||
}
|
}
|
||||||
@@ -533,11 +547,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn codex_responses_body_edits_preserve_existing_reasoning_but_use_codex_include() {
|
fn codex_responses_body_edits_preserve_existing_include_and_parallel_tool_calls() {
|
||||||
let mut provider_request_body = json!( {
|
let mut provider_request_body = json!( {
|
||||||
"input": [],
|
"input": [],
|
||||||
"model": "gpt-5.4",
|
"model": "gpt-5.4",
|
||||||
"include": ["file_search_call.results"],
|
"include": [
|
||||||
|
"file_search_call.results",
|
||||||
|
"web_search_call.results",
|
||||||
|
"web_search_call.action.sources",
|
||||||
|
"message.input_image.image_url",
|
||||||
|
"computer_call_output.output.image_url",
|
||||||
|
"code_interpreter_call.outputs",
|
||||||
|
"message.output_text.logprobs"
|
||||||
|
],
|
||||||
"reasoning": {"effort": "high", "summary": "detailed"},
|
"reasoning": {"effort": "high", "summary": "detailed"},
|
||||||
"parallel_tool_calls": false
|
"parallel_tool_calls": false
|
||||||
});
|
});
|
||||||
@@ -557,9 +579,18 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
provider_request_body["include"],
|
provider_request_body["include"],
|
||||||
json!(["reasoning.encrypted_content"])
|
json!([
|
||||||
|
"file_search_call.results",
|
||||||
|
"web_search_call.results",
|
||||||
|
"web_search_call.action.sources",
|
||||||
|
"message.input_image.image_url",
|
||||||
|
"computer_call_output.output.image_url",
|
||||||
|
"code_interpreter_call.outputs",
|
||||||
|
"message.output_text.logprobs",
|
||||||
|
"reasoning.encrypted_content"
|
||||||
|
])
|
||||||
);
|
);
|
||||||
assert_eq!(provider_request_body["parallel_tool_calls"], json!(true));
|
assert_eq!(provider_request_body["parallel_tool_calls"], json!(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -577,7 +608,10 @@ mod tests {
|
|||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(provider_request_body["reasoning"]["effort"], json!("medium"));
|
assert_eq!(
|
||||||
|
provider_request_body["reasoning"]["effort"],
|
||||||
|
json!("medium")
|
||||||
|
);
|
||||||
assert_eq!(provider_request_body["reasoning"]["summary"], json!("auto"));
|
assert_eq!(provider_request_body["reasoning"]["summary"], json!("auto"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
provider_request_body["include"],
|
provider_request_body["include"],
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ use serde_json::Value;
|
|||||||
use crate::formats::shared::model_directives::apply_model_directive_overrides_from_request;
|
use crate::formats::shared::model_directives::apply_model_directive_overrides_from_request;
|
||||||
|
|
||||||
use crate::formats::openai::responses::codex::{
|
use crate::formats::openai::responses::codex::{
|
||||||
apply_codex_openai_responses_chat_body_edits,
|
apply_codex_openai_responses_chat_body_edits, apply_codex_openai_responses_special_body_edits,
|
||||||
apply_codex_openai_responses_special_body_edits,
|
|
||||||
apply_openai_responses_compact_special_body_edits,
|
apply_openai_responses_compact_special_body_edits,
|
||||||
};
|
};
|
||||||
use crate::formats::shared::standard_normalize::build_local_openai_chat_request_body_with_model_directives;
|
use crate::formats::shared::standard_normalize::build_local_openai_chat_request_body_with_model_directives;
|
||||||
|
|||||||
@@ -1536,25 +1536,22 @@ fn map_auth_api_key_export_row(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{
|
||||||
CREATE_STANDALONE_API_KEY_SQL, CREATE_USER_API_KEY_SQL,
|
SqlxAuthApiKeySnapshotReadRepository, CREATE_STANDALONE_API_KEY_SQL,
|
||||||
SqlxAuthApiKeySnapshotReadRepository, UPDATE_STANDALONE_API_KEY_BASIC_SQL,
|
CREATE_USER_API_KEY_SQL, UPDATE_STANDALONE_API_KEY_BASIC_SQL,
|
||||||
};
|
};
|
||||||
use crate::driver::postgres::{PostgresPoolConfig, PostgresPoolFactory};
|
use crate::driver::postgres::{PostgresPoolConfig, PostgresPoolFactory};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_api_key_sql_orders_expiry_before_standalone_flags() {
|
fn create_api_key_sql_orders_expiry_before_standalone_flags() {
|
||||||
assert!(CREATE_USER_API_KEY_SQL.contains(
|
assert!(CREATE_USER_API_KEY_SQL
|
||||||
"expires_at,\n auto_delete_on_expiry,\n is_locked,\n is_standalone,"
|
.contains("expires_at,\n auto_delete_on_expiry,\n is_locked,\n is_standalone,"));
|
||||||
));
|
assert!(
|
||||||
assert!(CREATE_USER_API_KEY_SQL.contains(
|
CREATE_USER_API_KEY_SQL.contains("$12,\n $13,\n $14,\n FALSE,\n FALSE,\n $15,")
|
||||||
"$12,\n $13,\n FALSE,\n FALSE,\n $14,"
|
);
|
||||||
));
|
assert!(CREATE_STANDALONE_API_KEY_SQL
|
||||||
assert!(CREATE_STANDALONE_API_KEY_SQL.contains(
|
.contains("expires_at,\n auto_delete_on_expiry,\n is_locked,\n is_standalone,"));
|
||||||
"expires_at,\n auto_delete_on_expiry,\n is_locked,\n is_standalone,"
|
assert!(CREATE_STANDALONE_API_KEY_SQL
|
||||||
));
|
.contains("$12,\n $13,\n $14,\n FALSE,\n TRUE,\n $15,"));
|
||||||
assert!(CREATE_STANDALONE_API_KEY_SQL.contains(
|
|
||||||
"$12,\n $13,\n FALSE,\n TRUE,\n $14,"
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
372
dev.sh
372
dev.sh
@@ -1,372 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# 本地开发启动脚本
|
|
||||||
set -euo pipefail
|
|
||||||
clear >/dev/null 2>&1 || true
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<'EOF'
|
|
||||||
用法:
|
|
||||||
./dev.sh 启动本地 aether-gateway
|
|
||||||
./dev.sh --migrate 执行数据库迁移后退出
|
|
||||||
./dev.sh --apply-backfills
|
|
||||||
执行数据库回填后退出
|
|
||||||
./dev.sh --help 显示帮助
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
RUN_MIGRATE_ONLY=false
|
|
||||||
RUN_APPLY_BACKFILLS_ONLY=false
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case "$1" in
|
|
||||||
--migrate)
|
|
||||||
RUN_MIGRATE_ONLY=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--apply-backfills)
|
|
||||||
RUN_APPLY_BACKFILLS_ONLY=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--help|-h)
|
|
||||||
usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "=> 未知参数: $1"
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# 加载 .env 文件
|
|
||||||
set -a
|
|
||||||
source .env
|
|
||||||
set +a
|
|
||||||
|
|
||||||
dotenv_has_key() {
|
|
||||||
local key="$1"
|
|
||||||
rg -q "^[[:space:]]*${key}=" .env
|
|
||||||
}
|
|
||||||
|
|
||||||
lowercase() {
|
|
||||||
printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_uses_sqlite_database() {
|
|
||||||
local driver
|
|
||||||
local url
|
|
||||||
driver="$(lowercase "${AETHER_DATABASE_DRIVER:-}")"
|
|
||||||
url="${AETHER_DATABASE_URL:-${DATABASE_URL:-}}"
|
|
||||||
|
|
||||||
[[ "${driver}" == "sqlite" || "${url}" == sqlite:* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_uses_postgres_database() {
|
|
||||||
local driver
|
|
||||||
local url
|
|
||||||
driver="$(lowercase "${AETHER_DATABASE_DRIVER:-}")"
|
|
||||||
url="${AETHER_DATABASE_URL:-${DATABASE_URL:-}}"
|
|
||||||
|
|
||||||
if [[ -z "${driver}" && -z "${url}" ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ "${driver}" == "postgres" || "${driver}" == "postgresql" || "${url}" == postgres:* || "${url}" == postgresql:* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_uses_redis_runtime() {
|
|
||||||
local backend
|
|
||||||
backend="$(lowercase "${AETHER_RUNTIME_BACKEND:-}")"
|
|
||||||
|
|
||||||
if [[ "${backend}" == "memory" ]]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
if [[ "${backend}" == "redis" ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
if dev_uses_sqlite_database; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
print_dev_infra_hint() {
|
|
||||||
echo "=> 本地开发依赖未就绪。"
|
|
||||||
echo "=> 请先启动 Postgres / Redis:"
|
|
||||||
echo "=> docker compose up -d postgres redis"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_postgres_hint() {
|
|
||||||
echo "=> PostgreSQL 未就绪。"
|
|
||||||
echo "=> 请先启动 Postgres:"
|
|
||||||
echo "=> docker compose up -d postgres"
|
|
||||||
}
|
|
||||||
|
|
||||||
check_postgres_ready() {
|
|
||||||
local host="$1"
|
|
||||||
local port="$2"
|
|
||||||
|
|
||||||
if command -v pg_isready >/dev/null 2>&1; then
|
|
||||||
pg_isready -h "${host}" -p "${port}" >/dev/null 2>&1
|
|
||||||
return $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v nc >/dev/null 2>&1; then
|
|
||||||
nc -z "${host}" "${port}" >/dev/null 2>&1
|
|
||||||
return $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
check_redis_ready() {
|
|
||||||
local host="$1"
|
|
||||||
local port="$2"
|
|
||||||
local password="$3"
|
|
||||||
|
|
||||||
if command -v redis-cli >/dev/null 2>&1; then
|
|
||||||
REDISCLI_AUTH="${password}" redis-cli -h "${host}" -p "${port}" ping >/dev/null 2>&1
|
|
||||||
return $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v nc >/dev/null 2>&1; then
|
|
||||||
nc -z "${host}" "${port}" >/dev/null 2>&1
|
|
||||||
return $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
preflight_dev_infra() {
|
|
||||||
local postgres_host="${DB_HOST:-localhost}"
|
|
||||||
local postgres_port="${DB_PORT:-5432}"
|
|
||||||
local redis_host="${REDIS_HOST:-localhost}"
|
|
||||||
local redis_port="${REDIS_PORT:-6379}"
|
|
||||||
local redis_password="${REDIS_PASSWORD:-}"
|
|
||||||
|
|
||||||
if dev_uses_postgres_database && ! check_postgres_ready "${postgres_host}" "${postgres_port}"; then
|
|
||||||
echo "=> PostgreSQL 不可用: ${postgres_host}:${postgres_port}"
|
|
||||||
print_dev_infra_hint
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if dev_uses_redis_runtime && ! check_redis_ready "${redis_host}" "${redis_port}" "${redis_password}"; then
|
|
||||||
echo "=> Redis 不可用: ${redis_host}:${redis_port}"
|
|
||||||
print_dev_infra_hint
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
preflight_postgres_only() {
|
|
||||||
local postgres_host="${DB_HOST:-localhost}"
|
|
||||||
local postgres_port="${DB_PORT:-5432}"
|
|
||||||
|
|
||||||
if ! check_postgres_ready "${postgres_host}" "${postgres_port}"; then
|
|
||||||
echo "=> PostgreSQL 不可用: ${postgres_host}:${postgres_port}"
|
|
||||||
print_postgres_hint
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 构建共享后端 URL。SQLite + memory 模式不注入 Redis,避免运行时误走 Redis 路径。
|
|
||||||
if dev_uses_postgres_database; then
|
|
||||||
export DATABASE_URL="postgresql://${DB_USER:-postgres}:${DB_PASSWORD}@${DB_HOST:-localhost}:${DB_PORT:-5432}/${DB_NAME:-aether}"
|
|
||||||
if ! dotenv_has_key "AETHER_GATEWAY_DATA_POSTGRES_URL"; then
|
|
||||||
export AETHER_GATEWAY_DATA_POSTGRES_URL="${DATABASE_URL}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if dev_uses_redis_runtime; then
|
|
||||||
export REDIS_URL=redis://:${REDIS_PASSWORD}@${REDIS_HOST:-localhost}:${REDIS_PORT:-6379}/0
|
|
||||||
if ! dotenv_has_key "AETHER_GATEWAY_DATA_REDIS_URL"; then
|
|
||||||
export AETHER_GATEWAY_DATA_REDIS_URL="${REDIS_URL}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
unset REDIS_URL
|
|
||||||
unset AETHER_GATEWAY_DATA_REDIS_URL
|
|
||||||
fi
|
|
||||||
if ! dotenv_has_key "AETHER_GATEWAY_DATA_ENCRYPTION_KEY"; then
|
|
||||||
export AETHER_GATEWAY_DATA_ENCRYPTION_KEY="${ENCRYPTION_KEY:-}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 开发环境连接池低配(节省内存)
|
|
||||||
export DB_POOL_SIZE=${DB_POOL_SIZE:-5}
|
|
||||||
export DB_MAX_OVERFLOW=${DB_MAX_OVERFLOW:-5}
|
|
||||||
export HTTP_MAX_CONNECTIONS=${HTTP_MAX_CONNECTIONS:-20}
|
|
||||||
export HTTP_KEEPALIVE_CONNECTIONS=${HTTP_KEEPALIVE_CONNECTIONS:-5}
|
|
||||||
|
|
||||||
GATEWAY_PID=""
|
|
||||||
GATEWAY_LOG_DIR=""
|
|
||||||
GATEWAY_LOG_FILE=""
|
|
||||||
STARTUP_WAIT_EARLY_EXIT=false
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
if [ -n "${GATEWAY_PID}" ]; then
|
|
||||||
echo ""
|
|
||||||
echo "=> 停止 aether-gateway..."
|
|
||||||
kill "${GATEWAY_PID}" >/dev/null 2>&1 || true
|
|
||||||
wait "${GATEWAY_PID}" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
if [ -n "${GATEWAY_LOG_FILE}" ] && [ -f "${GATEWAY_LOG_FILE}" ]; then
|
|
||||||
rm -f "${GATEWAY_LOG_FILE}"
|
|
||||||
fi
|
|
||||||
if [ -n "${GATEWAY_LOG_DIR}" ] && [ -d "${GATEWAY_LOG_DIR}" ]; then
|
|
||||||
rmdir "${GATEWAY_LOG_DIR}" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
create_gateway_log_file() {
|
|
||||||
local tmp_root="${TMPDIR:-/tmp}"
|
|
||||||
tmp_root="${tmp_root%/}"
|
|
||||||
|
|
||||||
GATEWAY_LOG_DIR="$(mktemp -d "${tmp_root}/aether-dev-startup.XXXXXX")"
|
|
||||||
GATEWAY_LOG_FILE="${GATEWAY_LOG_DIR}/gateway.log"
|
|
||||||
: > "${GATEWAY_LOG_FILE}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_startup_failure_hint() {
|
|
||||||
local log_file="$1"
|
|
||||||
|
|
||||||
if [ -n "${log_file}" ] && [ -f "${log_file}" ]; then
|
|
||||||
if rg --text -q "database schema is behind|run \`aether-gateway --migrate\` before starting the service" "${log_file}"; then
|
|
||||||
echo "=> 检测到数据库 schema 落后,请先执行: ./dev.sh --migrate"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if rg --text -q "database backfills are behind|run \`aether-gateway --apply-backfills\` before starting the service" "${log_file}"; then
|
|
||||||
echo "=> 检测到待执行 backfills,请执行: ./dev.sh --apply-backfills"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=> 未识别到明确的修复动作,请根据上面的日志继续排查。"
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_startup() {
|
|
||||||
local pid="$1"
|
|
||||||
local timeout_seconds="$2"
|
|
||||||
local service_name="$3"
|
|
||||||
shift 3
|
|
||||||
|
|
||||||
STARTUP_WAIT_EARLY_EXIT=false
|
|
||||||
|
|
||||||
local attempts=$((timeout_seconds * 10))
|
|
||||||
if [ "${attempts}" -lt 1 ]; then
|
|
||||||
attempts=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
for ((i = 0; i < attempts; i++)); do
|
|
||||||
if "$@" >/dev/null 2>&1; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! kill -0 "${pid}" >/dev/null 2>&1; then
|
|
||||||
STARTUP_WAIT_EARLY_EXIT=true
|
|
||||||
echo "=> ${service_name} 启动进程已提前退出,请检查上面的日志。"
|
|
||||||
print_startup_failure_hint "${GATEWAY_LOG_FILE}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
|
|
||||||
if "$@" >/dev/null 2>&1; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! kill -0 "${pid}" >/dev/null 2>&1; then
|
|
||||||
STARTUP_WAIT_EARLY_EXIT=true
|
|
||||||
echo "=> ${service_name} 启动进程已提前退出,请检查上面的日志。"
|
|
||||||
print_startup_failure_hint "${GATEWAY_LOG_FILE}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=> ${service_name} 在 ${timeout_seconds}s 内未通过启动检查。"
|
|
||||||
echo "=> 如果这是冷编译或存在并发 cargo 构建,可调大 *_STARTUP_TIMEOUT_SECONDS 后重试。"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# 本地开发默认约定:
|
|
||||||
# - Rust aether-gateway 绑定 APP_PORT,作为唯一公开入口
|
|
||||||
# - ./dev.sh 不再启动 Python 宿主;本地默认只验证 Rust-owned 路径
|
|
||||||
export APP_PORT=${APP_PORT:-8084}
|
|
||||||
export RUST_LOG=${RUST_LOG:-aether_gateway=info}
|
|
||||||
RUST_SERVICE_STARTUP_TIMEOUT_SECONDS=${RUST_SERVICE_STARTUP_TIMEOUT_SECONDS:-180}
|
|
||||||
GATEWAY_STARTUP_TIMEOUT_SECONDS=${GATEWAY_STARTUP_TIMEOUT_SECONDS:-${RUST_SERVICE_STARTUP_TIMEOUT_SECONDS}}
|
|
||||||
|
|
||||||
if ! command -v cargo >/dev/null 2>&1; then
|
|
||||||
echo "=> 未找到 cargo,无法启动 aether-gateway。请先安装 Rust toolchain。"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
export AETHER_GATEWAY_VIDEO_TASK_TRUTH_SOURCE_MODE=${AETHER_GATEWAY_VIDEO_TASK_TRUTH_SOURCE_MODE:-rust-authoritative}
|
|
||||||
|
|
||||||
if [ "${RUN_MIGRATE_ONLY}" = "true" ] && [ "${RUN_APPLY_BACKFILLS_ONLY}" = "true" ]; then
|
|
||||||
if dev_uses_postgres_database && ! preflight_postgres_only; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=> 执行 aether-gateway 数据库迁移..."
|
|
||||||
cargo run -q -p aether-gateway -- --migrate
|
|
||||||
echo "=> 执行 aether-gateway 数据库回填..."
|
|
||||||
cargo run -q -p aether-gateway -- --apply-backfills
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${RUN_MIGRATE_ONLY}" = "true" ]; then
|
|
||||||
if dev_uses_postgres_database && ! preflight_postgres_only; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=> 执行 aether-gateway 数据库迁移..."
|
|
||||||
cargo run -q -p aether-gateway -- --migrate
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${RUN_APPLY_BACKFILLS_ONLY}" = "true" ]; then
|
|
||||||
if dev_uses_postgres_database && ! preflight_postgres_only; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=> 执行 aether-gateway 数据库回填..."
|
|
||||||
cargo run -q -p aether-gateway -- --apply-backfills
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! preflight_dev_infra; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
GATEWAY_ARGS=(--app-port "${APP_PORT}")
|
|
||||||
create_gateway_log_file
|
|
||||||
echo "=> 启动 aether-gateway (Rust frontdoor: 0.0.0.0:${APP_PORT})..."
|
|
||||||
echo "=> 日志过滤: ${RUST_LOG} (需要更详细日志可用: RUST_LOG=aether_gateway=debug ./dev.sh)"
|
|
||||||
echo "=> 执行命令: cargo run -p aether-gateway -- ${GATEWAY_ARGS[*]}"
|
|
||||||
cargo run -p aether-gateway -- "${GATEWAY_ARGS[@]}" > >(tee -a "${GATEWAY_LOG_FILE}") 2>&1 &
|
|
||||||
GATEWAY_PID=$!
|
|
||||||
|
|
||||||
if ! wait_for_startup "${GATEWAY_PID}" "${GATEWAY_STARTUP_TIMEOUT_SECONDS}" "aether-gateway" curl -sf "http://127.0.0.1:${APP_PORT}/_gateway/health"; then
|
|
||||||
if [ "${STARTUP_WAIT_EARLY_EXIT}" = "true" ]; then
|
|
||||||
GATEWAY_PID=""
|
|
||||||
fi
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if wait "${GATEWAY_PID}"; then
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
gateway_exit_code=$?
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${gateway_exit_code}" -ne 130 ] && [ "${gateway_exit_code}" -ne 143 ]; then
|
|
||||||
echo "=> aether-gateway 运行失败并已退出,请检查上面的日志。"
|
|
||||||
print_startup_failure_hint "${GATEWAY_LOG_FILE}"
|
|
||||||
fi
|
|
||||||
exit "${gateway_exit_code}"
|
|
||||||
Reference in New Issue
Block a user