新增cdsl
This commit is contained in:
@@ -12,6 +12,7 @@ from app.settings import Settings
|
||||
|
||||
TASK_ID = re.compile(r"^cad_[a-z0-9]{12}$")
|
||||
CONVERSATION_ID = re.compile(r"^conv_[a-z0-9]{12}$")
|
||||
DESIGN_INTENT_ID = re.compile(r"^intent_[a-z0-9]{12}$")
|
||||
|
||||
|
||||
def now_iso() -> str:
|
||||
@@ -36,6 +37,13 @@ def safe_conversation_id(conversation_id: str) -> str:
|
||||
return value
|
||||
|
||||
|
||||
def safe_design_intent_id(intent_id: str) -> str:
|
||||
value = str(intent_id or "").strip()
|
||||
if not DESIGN_INTENT_ID.fullmatch(value):
|
||||
raise ValueError("Invalid design intent id")
|
||||
return value
|
||||
|
||||
|
||||
def safe_relative_path(value: str) -> str:
|
||||
path = Path(str(value or ""))
|
||||
if not value or path.is_absolute() or ".." in path.parts:
|
||||
@@ -102,7 +110,7 @@ class WorkspaceStore:
|
||||
write_json(path, current)
|
||||
return current
|
||||
record = {
|
||||
"schema_version": "1.0",
|
||||
"schema_version": "1.1",
|
||||
"conversation_id": cid,
|
||||
"created_at": now_iso(),
|
||||
"updated_at": now_iso(),
|
||||
@@ -144,12 +152,14 @@ class WorkspaceStore:
|
||||
task_dir = self.task_dir(tid)
|
||||
(task_dir / "revisions").mkdir(parents=True, exist_ok=True)
|
||||
record = {
|
||||
"schema_version": "1.0",
|
||||
"schema_version": "1.1",
|
||||
"task_id": tid,
|
||||
"request": request,
|
||||
"created_at": now_iso(),
|
||||
"updated_at": now_iso(),
|
||||
"current_revision": "",
|
||||
"current_design_intent_id": "",
|
||||
"design_intents": [],
|
||||
"revisions": [],
|
||||
}
|
||||
write_json(path, record)
|
||||
@@ -171,6 +181,81 @@ class WorkspaceStore:
|
||||
write_json(self.task_path(task_id), task)
|
||||
return task
|
||||
|
||||
def create_design_intent(
|
||||
self,
|
||||
task_id: str | None,
|
||||
request: str,
|
||||
intent: dict[str, Any],
|
||||
part_skill_selection: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""Persist a validated plan and atomically make it the current plan."""
|
||||
task = self.ensure_task(task_id, request)
|
||||
task.setdefault("design_intents", [])
|
||||
task.setdefault("current_design_intent_id", "")
|
||||
task["schema_version"] = "1.1"
|
||||
previous_id = str(task.get("current_design_intent_id") or "")
|
||||
if previous_id:
|
||||
for record in task["design_intents"]:
|
||||
if str(record.get("intent_id") or "") == previous_id and record.get("status") != "superseded":
|
||||
record["status"] = "superseded"
|
||||
|
||||
intent_id = new_id("intent")
|
||||
created_at = now_iso()
|
||||
relative = Path("planning") / f"design-intent-{intent_id}.json"
|
||||
skill_ids = [str(item) for item in part_skill_selection.get("skill_ids") or [] if str(item)]
|
||||
persisted = dict(intent)
|
||||
persisted.update({
|
||||
"intent_id": intent_id,
|
||||
"created_at": created_at,
|
||||
"part_skill_ids": skill_ids,
|
||||
"part_skill_selection": part_skill_selection,
|
||||
})
|
||||
write_json(self.artifact_path(task["task_id"], relative.as_posix()), persisted)
|
||||
record = {
|
||||
"intent_id": intent_id,
|
||||
"status": "accepted" if persisted.get("status") == "ready" else "pending",
|
||||
"created_at": created_at,
|
||||
"path": relative.as_posix(),
|
||||
"part_skill_ids": skill_ids,
|
||||
"base_revision_id": str(persisted.get("base_revision_id") or ""),
|
||||
}
|
||||
task["design_intents"].append(record)
|
||||
task["current_design_intent_id"] = intent_id
|
||||
task["updated_at"] = now_iso()
|
||||
write_json(self.task_path(task["task_id"]), task)
|
||||
return {"task_id": task["task_id"], **record, "intent": persisted}
|
||||
|
||||
def read_design_intent(self, task_id: str, intent_id: str | None = None) -> dict[str, Any] | None:
|
||||
task = self.read_task(task_id)
|
||||
if not task:
|
||||
return None
|
||||
chosen = safe_design_intent_id(intent_id) if intent_id else str(task.get("current_design_intent_id") or "")
|
||||
if not chosen:
|
||||
return None
|
||||
record = next(
|
||||
(item for item in task.get("design_intents") or [] if str(item.get("intent_id") or "") == chosen),
|
||||
None,
|
||||
)
|
||||
if not isinstance(record, dict):
|
||||
return None
|
||||
path = self.artifact_path(task_id, str(record.get("path") or ""))
|
||||
intent = read_json(path)
|
||||
if not isinstance(intent, dict):
|
||||
return None
|
||||
return {"task_id": task_id, "record": record, "intent": intent}
|
||||
|
||||
def update_design_intent_status(self, task_id: str, intent_id: str, status: str) -> dict[str, Any]:
|
||||
safe_id = safe_design_intent_id(intent_id)
|
||||
task = self.ensure_task(task_id, "")
|
||||
records = task.setdefault("design_intents", [])
|
||||
record = next((item for item in records if str(item.get("intent_id") or "") == safe_id), None)
|
||||
if not isinstance(record, dict):
|
||||
raise ValueError("Design intent not found")
|
||||
record["status"] = str(status)
|
||||
task["updated_at"] = now_iso()
|
||||
write_json(self.task_path(task_id), task)
|
||||
return record
|
||||
|
||||
def read_task(self, task_id: str) -> dict[str, Any] | None:
|
||||
return read_json(self.task_path(task_id))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user