auto-save 2026-05-27 17:13 (~2)

This commit is contained in:
2026-05-27 17:13:16 +08:00
parent ec38215dd5
commit 8999fe0baf
2 changed files with 123 additions and 36 deletions

View File

@@ -1,31 +1,5 @@
{
"entries": [
{
"files_changed": 1,
"message": "Codex 会话活跃 · 最近命令codex · 分支 main · 1 项未提交变更 · 最近提交docs: record sharp text layout deployment",
"ts": "2026-05-20T11:25:31Z",
"type": "session-heartbeat"
},
{
"files_changed": 4,
"hash": "6f1bb5d",
"message": "auto-save 2026-05-20 19:33 (~4)",
"ts": "2026-05-20T19:33:19+08:00",
"type": "commit"
},
{
"files_changed": 3,
"hash": "e33463e",
"message": "fix: collapse subject agent confirmations",
"ts": "2026-05-20T19:33:51+08:00",
"type": "commit"
},
{
"files_changed": 1,
"message": "Codex 会话活跃 · 最近命令codex · 分支 main · 1 项未提交变更 · 最近提交fix: collapse subject agent confirmations",
"ts": "2026-05-20T11:35:31Z",
"type": "session-heartbeat"
},
{
"files_changed": 1,
"hash": "5b13a5c",
@@ -3194,6 +3168,34 @@
"message": "auto-save 2026-05-27 15:20 (~3)",
"hash": "fdef7f7",
"files_changed": 3
},
{
"ts": "2026-05-27T15:28:29+08:00",
"type": "commit",
"message": "auto-save 2026-05-27 15:26 (~3)",
"hash": "52e7a01",
"files_changed": 3
},
{
"ts": "2026-05-27T15:33:10+08:00",
"type": "commit",
"message": "docs: record canvas click performance optimization",
"hash": "685a6c4",
"files_changed": 1
},
{
"ts": "2026-05-27T15:50:24+08:00",
"type": "commit",
"message": "auto-save 2026-05-27 15:50 (~4)",
"hash": "2041282",
"files_changed": 4
},
{
"ts": "2026-05-27T15:54:22+08:00",
"type": "commit",
"message": "fix: persist uploaded canvas reference images",
"hash": "ec38215",
"files_changed": 4
}
]
}

View File

@@ -109,6 +109,10 @@ REWRITE_MODEL = gpt_model_env("REWRITE_MODEL")
VISION_MODEL = gpt_model_env("VISION_MODEL")
IMAGE_BASE_URL = os.getenv("IMAGE_BASE_URL", LLM_BASE_URL).strip()
IMAGE_API_KEY = os.getenv("IMAGE_API_KEY", LLM_API_KEY).strip()
ARK_IMAGE_BASE_URL = os.getenv("ARK_IMAGE_BASE_URL", "https://ark.cn-beijing.volces.com/api/v3").strip()
ARK_IMAGE_API_KEY = (os.getenv("ARK_IMAGE_API_KEY") or os.getenv("SEEDREAM_API_KEY") or "").strip()
ARK_SEEDREAM_IMAGE_MODEL = os.getenv("ARK_SEEDREAM_IMAGE_MODEL", "doubao-seedream-4-5-251128").strip() or "doubao-seedream-4-5-251128"
ARK_SEEDREAM_ENABLED = os.getenv("ARK_SEEDREAM_ENABLED", "true").strip().lower() not in {"0", "false", "no", "off"}
AI_HTTP_PROXY = (
os.getenv("AI_HTTP_PROXY")
or os.getenv("IMAGE_HTTP_PROXY")
@@ -118,15 +122,43 @@ AI_HTTP_PROXY = (
or os.getenv("http_proxy")
or ""
).strip()
# Product decision: gpt-image-2 remains the primary image model. Gemini is only
# allowed as an outage fallback when the primary gateway times out or returns
# transient upstream failures.
GPT_IMAGE_MODEL = "gpt-image-2"
DEFAULT_GPT_IMAGE_MODEL = "gpt-image-2"
GPT_IMAGE_MODEL = os.getenv("GPT_IMAGE_MODEL", DEFAULT_GPT_IMAGE_MODEL).strip() or DEFAULT_GPT_IMAGE_MODEL
IMAGE_MODEL = os.getenv("IMAGE_MODEL", GPT_IMAGE_MODEL).strip() or GPT_IMAGE_MODEL
IMAGE_FALLBACK_MODEL = os.getenv("IMAGE_FALLBACK_MODEL", "gemini-3-pro-image-preview").strip() or ""
IMAGE_FALLBACK_ENABLED = os.getenv("IMAGE_FALLBACK_ENABLED", "true").strip().lower() not in {"0", "false", "no", "off"}
IMAGE_MODEL = GPT_IMAGE_MODEL
PRODUCT_VIEW_MODEL = GPT_IMAGE_MODEL
SUBJECT_ASSET_IMAGE_MODEL = GPT_IMAGE_MODEL
IMAGE_FALLBACK_MODELS = [
item.strip()
for item in os.getenv("IMAGE_FALLBACK_MODELS", IMAGE_FALLBACK_MODEL).split(",")
if item.strip()
]
IMAGE_EXTRA_MODELS = [
item.strip()
for item in os.getenv("IMAGE_EXTRA_MODELS", "").split(",")
if item.strip()
]
PRODUCT_VIEW_MODEL = os.getenv("PRODUCT_VIEW_MODEL", GPT_IMAGE_MODEL).strip() or GPT_IMAGE_MODEL
SUBJECT_ASSET_IMAGE_MODEL = os.getenv("SUBJECT_ASSET_IMAGE_MODEL", IMAGE_MODEL).strip() or IMAGE_MODEL
IMAGE_MODEL_CONFIGS_JSON = os.getenv("IMAGE_MODEL_CONFIGS_JSON", "").strip()
try:
_IMAGE_MODEL_CONFIG_OVERRIDES_RAW = json.loads(IMAGE_MODEL_CONFIGS_JSON) if IMAGE_MODEL_CONFIGS_JSON else {}
if isinstance(_IMAGE_MODEL_CONFIG_OVERRIDES_RAW, list):
IMAGE_MODEL_CONFIG_OVERRIDES = {
str(item.get("id") or item.get("model")).strip(): item
for item in _IMAGE_MODEL_CONFIG_OVERRIDES_RAW
if isinstance(item, dict) and (item.get("id") or item.get("model"))
}
elif isinstance(_IMAGE_MODEL_CONFIG_OVERRIDES_RAW, dict):
IMAGE_MODEL_CONFIG_OVERRIDES = {
str(key).strip(): value
for key, value in _IMAGE_MODEL_CONFIG_OVERRIDES_RAW.items()
if str(key).strip() and isinstance(value, dict)
}
else:
IMAGE_MODEL_CONFIG_OVERRIDES = {}
except Exception as e:
print(f"[image config] invalid IMAGE_MODEL_CONFIGS_JSON ignored: {e}", flush=True)
IMAGE_MODEL_CONFIG_OVERRIDES = {}
IMAGE_SIZE_CHOICES = [
{
"id": "auto",
@@ -153,6 +185,54 @@ IMAGE_SIZE_CHOICES = [
"description": "适合横版封面和详情页配图",
},
]
ARK_SEEDREAM_SIZE_CHOICES = [
{
"id": "2K",
"label": "自动 2K",
"value": "2K",
"description": "Seedream 自行决定接近 2K 的输出尺寸",
},
{
"id": "2048x2048",
"label": "方图 2048",
"value": "2048x2048",
"description": "Seedream 方图,满足 4.5 最低像素要求",
},
{
"id": "1440x2560",
"label": "竖图 9:16",
"value": "1440x2560",
"description": "Seedream 竖版营销图",
},
{
"id": "2560x1440",
"label": "横图 16:9",
"value": "2560x1440",
"description": "Seedream 横版封面或网页图",
},
{
"id": "2160x2160",
"label": "方图 2160",
"value": "2160x2160",
"description": "Seedream 高清方图",
},
{
"id": "2160x3840",
"label": "竖图 4K",
"value": "2160x3840",
"description": "Seedream 竖版高分辨率输出",
},
{
"id": "3840x2160",
"label": "横图 4K",
"value": "3840x2160",
"description": "Seedream 横版高分辨率输出",
},
]
ALL_IMAGE_SIZE_CHOICES = IMAGE_SIZE_CHOICES + [
item for item in ARK_SEEDREAM_SIZE_CHOICES
if item["value"] not in {base["value"] for base in IMAGE_SIZE_CHOICES}
]
VIDEO_SIZE_CHOICES = [
{
"id": "720x1280",
@@ -183,9 +263,14 @@ SubjectModelBundle = Literal["gpt", "gemini"]
SubjectAgentMode = Literal["realistic", "cartoon", "elements", "custom"]
SUBJECT_AGENT_GPT_MODEL = gpt_model_env("SUBJECT_AGENT_GPT_MODEL", VISION_MODEL)
SUBJECT_AGENT_GEMINI_MODEL = os.getenv("SUBJECT_AGENT_GEMINI_MODEL", "gemini-2.5-flash").strip() or "gemini-2.5-flash"
SUBJECT_ASSET_IMAGE_MODELS = [GPT_IMAGE_MODEL] + (
[IMAGE_FALLBACK_MODEL] if IMAGE_FALLBACK_ENABLED and IMAGE_FALLBACK_MODEL and IMAGE_FALLBACK_MODEL != GPT_IMAGE_MODEL else []
)
SUBJECT_ASSET_IMAGE_MODELS = [
item.strip()
for item in os.getenv(
"SUBJECT_ASSET_IMAGE_MODELS",
",".join([SUBJECT_ASSET_IMAGE_MODEL, *IMAGE_FALLBACK_MODELS]),
).split(",")
if item.strip()
]
IMAGE_REQUEST_TIMEOUT_SECONDS = max(15, min(180, int(os.getenv("IMAGE_REQUEST_TIMEOUT_SECONDS", "60"))))
IMAGE_CIRCUIT_FAILURE_THRESHOLD = max(1, int(os.getenv("IMAGE_CIRCUIT_FAILURE_THRESHOLD", "2")))
IMAGE_CIRCUIT_COOLDOWN_SECONDS = max(60, int(os.getenv("IMAGE_CIRCUIT_COOLDOWN_SECONDS", "600")))