This commit is contained in:
@@ -157,6 +157,8 @@ class PlannerDecisionLogRow(Base):
|
||||
created_at: Mapped[str] = mapped_column(String, nullable=False)
|
||||
rationale: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
thinking: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
purpose: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
expected_outcome: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
|
||||
|
||||
class PluginRow(Base):
|
||||
|
||||
@@ -506,6 +506,8 @@ def create_internal_router(
|
||||
now=utc_now(),
|
||||
rationale=getattr(decision, "text_output", None),
|
||||
thinking=getattr(decision, "thinking", None),
|
||||
purpose=getattr(decision, "purpose", None),
|
||||
expected_outcome=getattr(decision, "expected_outcome", None),
|
||||
)
|
||||
logger.info(
|
||||
"planner-decision request resolved",
|
||||
@@ -518,6 +520,10 @@ def create_internal_router(
|
||||
return PlannerDecisionResponse(
|
||||
tool_name=decision.tool_name,
|
||||
arguments=dict(decision.arguments),
|
||||
rationale=getattr(decision, "text_output", None),
|
||||
thinking=getattr(decision, "thinking", None),
|
||||
purpose=getattr(decision, "purpose", None),
|
||||
expected_outcome=getattr(decision, "expected_outcome", None),
|
||||
input_tokens=(decision.usage.input_tokens if decision.usage else None),
|
||||
output_tokens=(decision.usage.output_tokens if decision.usage else None),
|
||||
total_tokens=(decision.usage.total_tokens if decision.usage else None),
|
||||
|
||||
@@ -147,6 +147,10 @@ class PlannerDecisionRequest(BaseModel):
|
||||
class PlannerDecisionResponse(BaseModel):
|
||||
tool_name: str
|
||||
arguments: dict[str, Any] = Field(default_factory=dict)
|
||||
rationale: str | None = None
|
||||
thinking: str | None = None
|
||||
purpose: str | None = None
|
||||
expected_outcome: str | None = None
|
||||
input_tokens: int | None = Field(default=None, ge=0)
|
||||
output_tokens: int | None = Field(default=None, ge=0)
|
||||
total_tokens: int | None = Field(default=None, ge=0)
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
"""Add reusable action metadata to planner_decision_log."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
revision = "0012_planner_decision_action_metadata"
|
||||
down_revision = "0011_planner_decision_log_reflection"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"planner_decision_log",
|
||||
sa.Column("purpose", sa.Text(), nullable=True),
|
||||
)
|
||||
op.add_column(
|
||||
"planner_decision_log",
|
||||
sa.Column("expected_outcome", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("planner_decision_log", "expected_outcome")
|
||||
op.drop_column("planner_decision_log", "purpose")
|
||||
@@ -136,6 +136,8 @@ class PlannerDecisionRecord:
|
||||
created_at: datetime
|
||||
rationale: str | None = None
|
||||
thinking: str | None = None
|
||||
purpose: str | None = None
|
||||
expected_outcome: str | None = None
|
||||
|
||||
|
||||
class CloudRepository(Protocol):
|
||||
@@ -522,6 +524,8 @@ class CloudRepository(Protocol):
|
||||
now: datetime,
|
||||
rationale: str | None = None,
|
||||
thinking: str | None = None,
|
||||
purpose: str | None = None,
|
||||
expected_outcome: str | None = None,
|
||||
) -> int:
|
||||
"""Insert one planner-decision log row, returning the assigned step_index.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from alembic.runtime.migration import MigrationContext
|
||||
from cloud.database import create_database_engine, normalize_database_url
|
||||
|
||||
|
||||
HEAD_REVISION = "0011_planner_decision_log_reflection"
|
||||
HEAD_REVISION = "0012_planner_decision_action_metadata"
|
||||
|
||||
|
||||
class SchemaVersionError(RuntimeError):
|
||||
|
||||
@@ -263,6 +263,10 @@ def create_cloud_router(
|
||||
user_prompt=rec.user_prompt,
|
||||
tool_name=rec.tool_name,
|
||||
arguments=parsed_args,
|
||||
rationale=rec.rationale,
|
||||
thinking=rec.thinking,
|
||||
purpose=rec.purpose,
|
||||
expected_outcome=rec.expected_outcome,
|
||||
created_at=rec.created_at,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -280,6 +280,10 @@ class TaskPlannerDecisionItem(BaseModel):
|
||||
user_prompt: str
|
||||
tool_name: str
|
||||
arguments: dict[str, Any] = Field(default_factory=dict)
|
||||
rationale: str | None = None
|
||||
thinking: str | None = None
|
||||
purpose: str | None = None
|
||||
expected_outcome: str | None = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
|
||||
@@ -1696,6 +1696,8 @@ class SQLAlchemyCloudRepository:
|
||||
now: datetime,
|
||||
rationale: str | None = None,
|
||||
thinking: str | None = None,
|
||||
purpose: str | None = None,
|
||||
expected_outcome: str | None = None,
|
||||
) -> int:
|
||||
with self._sessions.begin() as session:
|
||||
current_max = session.scalars(
|
||||
@@ -1718,6 +1720,8 @@ class SQLAlchemyCloudRepository:
|
||||
created_at=_iso(now),
|
||||
rationale=rationale,
|
||||
thinking=thinking,
|
||||
purpose=purpose,
|
||||
expected_outcome=expected_outcome,
|
||||
)
|
||||
)
|
||||
session.flush()
|
||||
@@ -1772,6 +1776,8 @@ class SQLAlchemyCloudRepository:
|
||||
created_at=_parse_dt(row.created_at), # type: ignore[arg-type]
|
||||
rationale=row.rationale,
|
||||
thinking=row.thinking,
|
||||
purpose=row.purpose,
|
||||
expected_outcome=row.expected_outcome,
|
||||
)
|
||||
for row in rows
|
||||
]
|
||||
@@ -1894,9 +1900,7 @@ class SQLAlchemyCloudRepository:
|
||||
CloudSkillEntitlementRow.skill_id == skill_id
|
||||
)
|
||||
)
|
||||
session.execute(
|
||||
delete(CloudSkillRow).where(CloudSkillRow.id == skill_id)
|
||||
)
|
||||
session.execute(delete(CloudSkillRow).where(CloudSkillRow.id == skill_id))
|
||||
|
||||
def list_entitlements_for_skill(self, skill_id: str) -> list[str]:
|
||||
with self._sessions() as session:
|
||||
@@ -1922,13 +1926,9 @@ class SQLAlchemyCloudRepository:
|
||||
skills.sort(key=lambda s: s.name_normalized)
|
||||
return skills
|
||||
|
||||
def grant_entitlement(
|
||||
self, skill_id: str, host_id: str, *, now: datetime
|
||||
) -> None:
|
||||
def grant_entitlement(self, skill_id: str, host_id: str, *, now: datetime) -> None:
|
||||
with self._sessions.begin() as session:
|
||||
existing = session.get(
|
||||
CloudSkillEntitlementRow, (skill_id, host_id)
|
||||
)
|
||||
existing = session.get(CloudSkillEntitlementRow, (skill_id, host_id))
|
||||
if existing is not None:
|
||||
return # idempotent
|
||||
session.add(
|
||||
@@ -1940,21 +1940,15 @@ class SQLAlchemyCloudRepository:
|
||||
)
|
||||
self._bump_host(session, host_id, skill_id, "upsert", now)
|
||||
|
||||
def revoke_entitlement(
|
||||
self, skill_id: str, host_id: str, *, now: datetime
|
||||
) -> None:
|
||||
def revoke_entitlement(self, skill_id: str, host_id: str, *, now: datetime) -> None:
|
||||
with self._sessions.begin() as session:
|
||||
existing = session.get(
|
||||
CloudSkillEntitlementRow, (skill_id, host_id)
|
||||
)
|
||||
existing = session.get(CloudSkillEntitlementRow, (skill_id, host_id))
|
||||
if existing is None:
|
||||
return
|
||||
session.delete(existing)
|
||||
self._bump_host(session, host_id, skill_id, "remove", now)
|
||||
|
||||
def fetch_host_delta(
|
||||
self, host_id: str, since_version: int | None
|
||||
) -> Any:
|
||||
def fetch_host_delta(self, host_id: str, since_version: int | None) -> Any:
|
||||
from cloud.skills import HostSkillDelta
|
||||
|
||||
with self._sessions.begin() as session:
|
||||
|
||||
Reference in New Issue
Block a user