feat: unify model selection and complete favorite settings

This commit is contained in:
chenmingxuan committed 2026-10-18 20:03:41 +08:00
1 parent a4a5430922
commit 50638d4130
24 files changed
+347 -90

No files matched your search

@@ -8,8 +8,10 @@ from artemis.config.settings import settings
def execution_config(item: dict) -> dict:
agent = load_agent_config()
model = parse_llm_config().operator
overrides = item.get("runtime_overrides") or {}
profile = overrides.get("profile") or item.get("profile") or "flash"
options = {
"profile": item.get("profile") or "flash",
"profile": profile,
"model": model.model,
"reasoning_effort": model.reasoning_effort or "default",
"request_timeout_seconds": model.timeout,
@@ -20,7 +22,7 @@ def execution_config(item: dict) -> dict:
"analyze_video": agent.video_analyzer.enable_ledger,
"timeout_seconds": settings.ARTEMIS_TASK_TIMEOUT_SECONDS,
"verification_level": verification_level_for_checker(agent.checker),
"explorer_mode": agent.explorer.resolve(profile=item.get("profile") or "flash"),
"explorer_mode": agent.explorer.resolve(profile=profile),
"observation_timeout_seconds": settings.ARTEMIS_OBSERVATION_TIMEOUT_SECONDS,
"observation_max_attempts": settings.ARTEMIS_OBSERVATION_MAX_ATTEMPTS,
"device_command_timeout_seconds": settings.ARTEMIS_DEVICE_COMMAND_TIMEOUT_SECONDS,
@@ -30,7 +32,6 @@ def execution_config(item: dict) -> dict:
for key in ("device_serial", "verification_level", "explorer_mode", "locked_app_package"):
if item.get(key) is not None:
options[key] = item[key]
overrides = item.get("runtime_overrides") or {}
options["recording"] = {**options["recording"], **(overrides.get("recording") or {})}
options.update({k: v for k, v in overrides.items() if k != "recording" and v is not None})
return {
+63 -5
View File
@@ -58,12 +58,70 @@ class FavoriteService:
value = self.store.get("favorite", identifier(key))
if value is None:
raise KeyError("收藏不存在")
if value.get("config_version") != 1:
# Complete legacy snapshots once and preserve their list position.
# Re-read under the write lock so a concurrent edit cannot be lost.
with self.store.connection() as conn:
conn.execute("BEGIN IMMEDIATE")
row = conn.execute(
"SELECT payload FROM automation_records WHERE kind='favorite' AND id=?", (key,)
).fetchone()
if row is None:
raise KeyError("收藏不存在")
value = self._complete(json.loads(row[0]))
conn.execute(
"UPDATE automation_records SET payload=? WHERE kind='favorite' AND id=?",
(json.dumps(value, ensure_ascii=False), key),
)
conn.commit()
return value
def list(self) -> list[dict]:
return [
self.get(item["id"]) if item.get("config_version") != 1 else item
for item in self.store.records("favorite", 10000)
]
def _complete(self, favorite: dict) -> dict:
result = deepcopy(favorite)
if result.get("config_version") == 1:
return result
snapshot = result["snapshot"]
if result["kind"] == "batch":
for case in snapshot["cases"]:
case["task_config"] = execution_config(
{
"profile": snapshot.get("profile"),
"device_serial": snapshot.get("device_serial"),
"runtime_overrides": {
"timeout_seconds": snapshot.get("timeout_seconds"),
**(case.get("task_config") or {}),
},
}
)["runtime_overrides"]
elif result["kind"] == "exploration":
config = ExplorationConfig.model_validate(snapshot.get("config") or {}).model_dump()
snapshot["config"] = config
snapshot["task_config"] = execution_config(
{
"runtime_overrides": {
**(snapshot.get("task_config") or {}),
**{
key: config[key]
for key in ("model", "reasoning_effort", "timeout_seconds")
},
}
}
)["runtime_overrides"]
else:
snapshot.update(execution_config(snapshot))
result["config_version"] = 1
return result
def _task(self, session_id: str, *, fallback: dict | None = None) -> tuple[dict, list[str]]:
job = self.store.job(session_id) or {}
if snapshot := job.get("execution_config"):
return deepcopy(snapshot), []
return execution_config(snapshot), []
row = SessionRepository(self.store.path).get_session_by_id(session_id) or {}
submission = job.get("submission") or fallback or {}
options = {
@@ -140,8 +198,8 @@ class FavoriteService:
def create(self, value: FavoriteCreate) -> dict:
token = f"{value.source_kind}:{value.source_id}:{value.version or ''}"
key = hashlib.sha256(token.encode()).hexdigest()[:32]
if existing := self.store.get("favorite", key):
return existing
if self.store.get("favorite", key):
return self.get(key)
snapshot, missing, kind, version = {}, [], value.source_kind, None
source_id = value.source_id
repo = ExplorationStore(self.store)
@@ -254,10 +312,10 @@ class FavoriteService:
}
if not favorite["name"]:
raise ValueError("收藏名称不能为空")
return self.store.put("favorite", key, favorite)
return self.store.put("favorite", key, self._complete(favorite))
def updated(self, favorite: dict, value: FavoriteUpdate) -> dict:
result = deepcopy(favorite)
result = self._complete(favorite)
if value.name is not None:
if not value.name.strip():
raise ValueError("收藏名称不能为空")
@@ -80,11 +80,9 @@ def get_model_settings() -> dict:
"tool_fallback_no_progress_attempts": settings.ARTEMIS_TOOL_FALLBACK_MAX_NO_PROGRESS_ATTEMPTS,
"reasoning_effort": settings.OPENAI_REASONING_EFFORT,
"model_presets": [
"gpt-6-luna",
"gpt-6.1-sol",
"gpt-6-astra",
"gpt-5.6-luna",
"gpt-6-luna",
"mimo-v2.6-flash",
"mimo-v2.6-pro",
],
"env_path": str(get_env_file()),
+1 -1
View File
@@ -103,7 +103,7 @@ def template() -> bytes:
json.dumps(
{
"profile": "pro",
"model": "mimo-v2.6-flash",
"model": "gpt-6-luna",
"reasoning_effort": "high",
"verification_level": "final",
"record_video": True,