refactor(agent): gate sustained goals behind explicit /goal

Replace the legacy long-goal skill contract with command-scoped goal tools and runtime guidance. Keep goal state durable across continuations while restricting create and replace mutations to explicit user /goal turns.
This commit is contained in:
chengyongru
2026-07-12 00:35:17 +08:00
committed by Xubin Ren
parent edf78e7054
commit 7f8c3453e1
24 changed files with 1131 additions and 375 deletions
+16 -10
View File
@@ -1,4 +1,4 @@
"""Session metadata helpers for sustained goals (e.g. ``long_task`` / ``complete_goal``).
"""Session metadata helpers for explicit sustained goals.
Tools set ``metadata[GOAL_STATE_KEY]``. Reads accept the legacy session key ``thread_goal``
for older sessions. Callers use ``goal_state_runtime_lines``, ``goal_state_ws_blob``, and
@@ -13,9 +13,10 @@ from typing import Any, Mapping, MutableMapping
from nanobot.session.manager import SessionManager
GOAL_STATE_KEY = "goal_state"
GOAL_COMMAND = "/goal"
MAX_GOAL_OBJECTIVE_CHARS = 4000
# Older builds stored the same JSON blob under this key.
_LEGACY_GOAL_STATE_SESSION_KEY = "thread_goal"
_MAX_OBJECTIVE_IN_RUNTIME = 4000
_MAX_OBJECTIVE_WS = 600
@@ -38,22 +39,27 @@ def goal_state_raw(metadata: Mapping[str, Any] | None) -> Any:
def sustained_goal_active(metadata: Mapping[str, Any] | None) -> bool:
"""True when this session has an active sustained objective (``long_task`` bookkeeping)."""
"""True when this session has an active sustained objective."""
goal = parse_goal_state(goal_state_raw(metadata))
return isinstance(goal, dict) and goal.get("status") == "active"
def explicit_goal_requested(message_metadata: Mapping[str, Any] | None) -> bool:
"""True when this turn was explicitly started by the ``/goal`` command."""
if not message_metadata:
return False
if message_metadata.get("goal_requested") is True:
return True
return str(message_metadata.get("original_command") or "").strip() == GOAL_COMMAND
def sustained_goal_turn(
metadata: Mapping[str, Any] | None,
*,
message_metadata: Mapping[str, Any] | None = None,
) -> bool:
"""True when this turn should use sustained-goal runtime limits."""
if sustained_goal_active(metadata):
return True
if not message_metadata:
return False
return str(message_metadata.get("original_command") or "").strip() == "/goal"
return sustained_goal_active(metadata) or explicit_goal_requested(message_metadata)
def parse_goal_state(blob: Any) -> dict[str, Any] | None:
@@ -80,8 +86,8 @@ def goal_state_runtime_lines(metadata: Mapping[str, Any] | None) -> list[str]:
objective = str(goal.get("objective") or "").strip()
if not objective:
return ["Goal: active (no objective text stored)."]
if len(objective) > _MAX_OBJECTIVE_IN_RUNTIME:
objective = objective[:_MAX_OBJECTIVE_IN_RUNTIME].rstrip() + "\n… (truncated)"
if len(objective) > MAX_GOAL_OBJECTIVE_CHARS:
objective = objective[:MAX_GOAL_OBJECTIVE_CHARS].rstrip() + "\n… (truncated)"
out = ["Goal (active):", objective]
hint = str(goal.get("ui_summary") or "").strip()
if hint:
+11 -4
View File
@@ -30,6 +30,8 @@ _GOAL_CONTINUATION_ROUNDS_KEY = "_sustained_goal_continuation_rounds"
_MAX_GOAL_CONTINUATION_ROUNDS = 12
_STRIPPED_INBOUND_META_KEYS = {
INTERNAL_CONTINUATION_PENDING_META,
"goal_requested",
"original_command",
}
@@ -168,7 +170,12 @@ def _continuation_available(
def clear_internal_continuation_state(metadata: MutableMapping[str, Any]) -> None:
"""Reset policy bookkeeping once its owning runtime mode is inactive."""
if not sustained_goal_active(metadata):
metadata.pop(_GOAL_CONTINUATION_ROUNDS_KEY, None)
reset_goal_continuation_rounds(metadata)
def reset_goal_continuation_rounds(metadata: MutableMapping[str, Any]) -> None:
"""Start a newly created or replaced goal with a fresh continuation budget."""
metadata.pop(_GOAL_CONTINUATION_ROUNDS_KEY, None)
def _save_skip_for_turn(
@@ -240,14 +247,14 @@ def _goal_continuation_prompt(metadata: Mapping[str, Any] | None) -> str:
"its tool-call budget.\n\n"
f"{goal}\n\n"
"Continue from the saved context. Do not mention the continuation "
"boundary to the user. Use tools as needed, and call complete_goal "
"when the objective is truly finished."
"boundary to the user. Use tools as needed, and call update_goal "
"with action='complete' when the objective is truly finished."
)
return (
"Continue the active sustained goal after the previous turn reached "
"its tool-call budget. Continue from the saved context. Do not mention "
"the continuation boundary to the user. Use tools as needed, and call "
"complete_goal when the objective is truly finished."
"update_goal with action='complete' when the objective is truly finished."
)