feat: prepare 2.2.0 with UI and execution fixes
Add dark theme, richer Markdown and readable plugin results. Improve Android input evidence, response integrity and diagnostics. Unify lifecycle, guidance receipts and evidence sources across clients. Keep direct action dispatch without an added AI quota approval layer. Align version metadata at 2.2.0 and bundle Helper 1.2.2. Validation: 3063 backend tests before the version bump; 44 after. Frontend: 317 tests and production build passed.
This commit is contained in:
1 parent
83bcfd54d5
commit
fac4ccb760
146 files changed
+5689
-2033
No files matched your search
@@ -3,13 +3,15 @@
|
||||
import json
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||||
|
||||
from artemis.core.tool_declaration import ToolDeclaration
|
||||
from artemis.utils.notes import save_verified_note
|
||||
|
||||
|
||||
class Stage(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
id: str = Field(min_length=1, max_length=80)
|
||||
scope: str = Field(
|
||||
min_length=1,
|
||||
@@ -30,6 +32,8 @@ class Stage(BaseModel):
|
||||
|
||||
|
||||
class ProgressUpdate(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
stages: list[Stage] = Field(min_length=1, max_length=16)
|
||||
reason: str = Field(
|
||||
min_length=1,
|
||||
@@ -53,13 +57,41 @@ class ProgressUpdate(BaseModel):
|
||||
return self
|
||||
|
||||
|
||||
class StageUpdate(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
id: str = Field(min_length=1, max_length=80)
|
||||
status: Literal["pending", "active", "done", "blocked"]
|
||||
evidence: str | None = Field(default=None, max_length=1200)
|
||||
|
||||
|
||||
class ProgressInput(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
stages: list[Stage] | None = Field(default=None, min_length=1, max_length=16)
|
||||
stage_updates: list[StageUpdate] | None = Field(default=None, min_length=1, max_length=16)
|
||||
reason: str = Field(min_length=1, max_length=600)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def one_update_form(self):
|
||||
if (self.stages is None) == (self.stage_updates is None):
|
||||
raise ValueError("stages 与 stage_updates 必须且只能提供一种")
|
||||
if self.stage_updates and len({s.id for s in self.stage_updates}) != len(
|
||||
self.stage_updates
|
||||
):
|
||||
raise ValueError("阶段补丁 id 不能重复")
|
||||
return self
|
||||
|
||||
|
||||
PROGRESS_TOOL = ToolDeclaration(
|
||||
"update_task_progress",
|
||||
"Record ordered stages for a cross-resource task before acting. Follow the user's sequence; "
|
||||
"read-only preflight is allowed on other resources. Update only at stage boundaries or genuine "
|
||||
"replanning, not every turn. Can precede the next action in the same tool-call list. "
|
||||
"Initialize/replan with all stages, or use stage_updates [{id,status,evidence?}] for existing IDs; "
|
||||
"patches preserve other stages and their order/scope/resources. Never provide both forms. "
|
||||
"Keep outstanding scope; done requires recorded evidence. This ledger does not verify business success.",
|
||||
ProgressUpdate.model_json_schema(),
|
||||
ProgressInput.model_json_schema(),
|
||||
)
|
||||
|
||||
|
||||
@@ -69,7 +101,27 @@ class TaskProgress:
|
||||
self.last_resource: str | None = None
|
||||
|
||||
def update(self, args: dict, *, resources: set[str], directory=None) -> str:
|
||||
update = ProgressUpdate.model_validate(args)
|
||||
incoming = ProgressInput.model_validate(args)
|
||||
stages = incoming.stages
|
||||
if incoming.stage_updates:
|
||||
if self.value is None:
|
||||
raise ValueError("首次记录必须提供完整 stages,不能仅提供阶段补丁")
|
||||
updates = {s.id: s for s in incoming.stage_updates}
|
||||
unknown = set(updates) - {s.id for s in self.value.stages}
|
||||
if unknown:
|
||||
raise ValueError(
|
||||
f"阶段补丁引用了未知 id:{sorted(unknown)};新增阶段须提供完整 stages"
|
||||
)
|
||||
stages = [
|
||||
{
|
||||
**stage.model_dump(),
|
||||
**updates[stage.id].model_dump(exclude_none=True),
|
||||
}
|
||||
if stage.id in updates
|
||||
else stage.model_dump()
|
||||
for stage in self.value.stages
|
||||
]
|
||||
update = ProgressUpdate.model_validate({"stages": stages, "reason": incoming.reason})
|
||||
if any(set(stage.resources) - resources for stage in update.stages):
|
||||
raise ValueError(f"阶段引用了不可用资源;可用:{sorted(resources)}")
|
||||
if self.value:
|
||||
|
||||
Reference in new issue
Block a user