Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
155 commits
Select commit Hold shift + click to select a range
ee3fe4f
Refactor _validate_plan_forward to use option model directly
yichao-liang Apr 1, 2026
58b86cd
Unify backtracking refinement search into shared run_backtracking_ref…
yichao-liang Apr 1, 2026
e7eaf05
Simplify _validate_plan_forward to use run_backtracking_refinement
yichao-liang Apr 1, 2026
43acbf2
Refactor _current_observation/_current_state usage in pybullet_env
yichao-liang Apr 2, 2026
57ef4b8
Add CFG option to load plan sketch from file instead of LLM
yichao-liang Apr 2, 2026
d0ac199
Remove redundant conditions from Place action in boil_plan_sketch
yichao-liang Apr 2, 2026
0cafcd8
Scale target joint value based on switch_joint_scale in PyBulletBoilEnv
yichao-liang Apr 2, 2026
3808337
Refactor _terminal in option model to deduplicate wait-termination logic
yichao-liang Apr 7, 2026
3624d01
Refactor terminal state logging in _OracleOptionModel to simplify con…
yichao-liang Apr 7, 2026
80c8110
Format docstring in get_observation method for improved readability
yichao-liang Apr 7, 2026
d3ad209
Refactor PyBulletEnv for readability and better naming
yichao-liang Apr 7, 2026
5bf6af3
Regroup PyBulletEnv methods by responsibility and update docstring
yichao-liang Apr 7, 2026
59aac01
Refactor PyBulletEnv: extract _domain_specific_step from step()
yichao-liang Apr 8, 2026
f86c0ea
Update PyBulletEnv module docstring for step() refactoring
yichao-liang Apr 8, 2026
9cddb03
Add skip_process_dynamics constructor param to PyBulletEnv
yichao-liang Apr 8, 2026
989cf4e
Extract run_query_sync helper to remove duplicated async-to-sync brid…
yichao-liang Apr 13, 2026
87bbe1c
Refactor main function: extract and modularize setup logic for clarit…
yichao-liang Apr 14, 2026
10f010b
Rename agent explorer to agent_plan for clearer naming
yichao-liang Apr 14, 2026
4076abd
Move AgentSessionMixin into agent_sdk package
yichao-liang Apr 14, 2026
b264291
Add AgentBilevelExplorer for sim-learning experiments
yichao-liang Apr 14, 2026
ee0a2b7
Add explorer-specific sample budget and experiment-plan logging
yichao-liang Apr 16, 2026
a8fb2dd
Add sim-learning approach and synthesis tooling
yichao-liang Apr 16, 2026
f392458
Update experiment configs for sim-learning
yichao-liang Apr 16, 2026
7663d05
Refactor sim-learning: extract primitives, add GT simulator factory
yichao-liang Apr 16, 2026
9970dd4
Fix formatting, pylint, and mypy issues for CI compliance
yichao-liang Apr 16, 2026
8ff80a4
Update test setup to use test tasks for boil environment and refine t…
yichao-liang Apr 16, 2026
54002dd
Refactor combined model in GT simulator
yichao-liang Apr 16, 2026
cb405d9
Fix expected-atoms check to support DerivedPredicates
yichao-liang Apr 17, 2026
6c92572
Skip kinematic reset in PyBullet when only non-kinematic state changed
yichao-liang Apr 17, 2026
c9723f2
Support offline dataset learning in AgentSimLearningApproach
yichao-liang Apr 17, 2026
cccb7e2
Log periodic progress during MCMC parameter fitting
yichao-liang Apr 17, 2026
ec3b9f3
Fix mypy and pylint errors for CI compliance
yichao-liang Apr 17, 2026
e8e3675
Apply yapf, isort, and docformatter across the codebase
yichao-liang Apr 17, 2026
328b4d7
Inline approach configs into parent files in predicatorv3
Apr 28, 2026
6735ac8
Preserve robot joint config across PyBullet state save/restore
Apr 28, 2026
ebb3304
Add 'emcee' to the list of install_requires in setup.py
yichao-liang Apr 28, 2026
0bc5234
Force PyBullet FK refresh and skip redundant finger snap
yichao-liang Apr 29, 2026
e84d788
Apply yapf/docformatter to satisfy CI autoformat check
yichao-liang Apr 29, 2026
8333b0f
Configure predicatorv3 demos for offline-only sim-learning runs
yichao-liang Apr 29, 2026
0b6a4b0
Add jug orientation handling in PyBulletBoilEnv
yichao-liang Apr 29, 2026
1b6c510
Revert getLinkState to PyBullet default (no computeForwardKinematics …
yichao-liang Apr 30, 2026
f0b4692
Add lo/hi bounds to ParamSpec and skip-MCMC support in fit_params
yichao-liang Apr 30, 2026
9c61f3e
Build boil param specs dynamically from CFG with lo/hi bounds
yichao-liang Apr 30, 2026
e08df54
Apply lo/hi clamping and configurable noise scale to oracle perturbation
yichao-liang Apr 30, 2026
e44a850
Update installation instructions and add macOS setup script for PyBullet
yichao-liang Apr 30, 2026
b8df145
Update PyBullet version to 3.2.7 and simplify macOS setup script
yichao-liang May 1, 2026
c033f9c
Refactor liquid color update logic and rename related methods for cla…
yichao-liang May 1, 2026
20a310e
Add more debug logging for CogMan and option execution flow
yichao-liang May 1, 2026
9d6b9e3
Handle PyBullet physics server crashes with env recreation and retry
yichao-liang May 1, 2026
99b38b1
Fix jug orientation handling in PyBulletBoilEnv by restoring rotation…
yichao-liang May 1, 2026
8521882
Update installation instructions and dependencies; remove macOS setup…
yichao-liang May 1, 2026
f998254
Remove mara_robosim dependency from setup.py
yichao-liang May 1, 2026
ea690a2
Merge remote-tracking branch 'origin/master' into sim-learning
yichao-liang May 1, 2026
4e12a17
Fix get_gt_simulator to use env_name instead of normalized name
yichao-liang May 2, 2026
a8105cf
Add before/after MSE, likelihood, and param-delta logging for paramet…
yichao-liang May 2, 2026
2f97798
Use SSE loss and wider walker init so MCMC parameter fitting actually…
yichao-liang May 3, 2026
9f09ff9
Move GT simulator components onto module-globals contract
yichao-liang May 4, 2026
c5d45c2
Soften boil parameter-dependent gates with sigmoid weights
yichao-liang May 4, 2026
95e384f
Add LM warm-start and Hessian identifiability diagnostic
yichao-liang May 4, 2026
195e889
Infer process-feature scope from base-sim residuals
yichao-liang May 4, 2026
124dd94
Skip MCMC and use LM warm-start in boil agent config
yichao-liang May 4, 2026
cc11084
Apply yapf and docformatter formatting
yichao-liang May 4, 2026
465177a
Silence mypy on PyBullet client-id attribute access
yichao-liang May 4, 2026
6e76660
Mark unused action arg in sim_fn to satisfy pylint
yichao-liang May 4, 2026
9415d12
Use per-component diff in _set_state to eliminate robot jitter
yichao-liang May 4, 2026
418fd30
Reposition recreated cups and plugs in coffee _set_domain_specific_state
yichao-liang May 4, 2026
e82df9d
Look up predicates lazily in option-model _abstract_function
yichao-liang May 4, 2026
8b6d709
Rename 'kinematics-only' to 'base-sim-only' in docs and test names
yichao-liang May 4, 2026
abc448f
Tighten _robot_matches_state atol so set_state hint forces reset
yichao-liang May 4, 2026
58f44f6
Fix flaky test_glib_explorer and test_demo_dataset_loading under pyte…
yichao-liang May 4, 2026
7bc4443
Add unit tests for _robot_matches_state atol and pybullet_helpers.obj…
yichao-liang May 4, 2026
275d049
Merge branch 'master' into sim-learning
yichao-liang May 5, 2026
3069f9c
Extract env-agnostic process-rule primitives to code_sim_learning/utils
yichao-liang May 5, 2026
d1b83c5
Make sim synthesis file-driven with versioned snapshots
yichao-liang May 5, 2026
b84fe61
Rename agent_sim_learning config to agent_rule_learning
yichao-liang May 5, 2026
b426ad0
Pin claude-agent-sdk>=0.1.73 and bump httpx to 0.28.1
yichao-liang May 6, 2026
4aa7a3a
Return CallToolResult-shape dict from synthesis MCP tools
yichao-liang May 6, 2026
82410d2
Resolve local-sandbox paths eagerly and use cwd-relative agent paths
yichao-liang May 6, 2026
9871846
Improve agent log readability
yichao-liang May 6, 2026
da3c539
Fix iter_feature_residuals type annotation and run autoformat
yichao-liang May 6, 2026
9fb8896
Disable oracle sim program in boil agent_rule_learning config
yichao-liang May 6, 2026
3e72402
Fix pylint import-outside-toplevel pragma stripped by yapf
yichao-liang May 6, 2026
5cf050b
Auto-scale plan-refinement timeout and surface termination details
yichao-liang May 6, 2026
0015618
Wire evaluate_plan_refinement to auto-scale and clarify its docs
yichao-liang May 6, 2026
01b9b6c
Clarify synthesis prompts and scrub domain-specific examples
yichao-liang May 6, 2026
f76b5bc
Require plan in evaluate_plan_refinement and drop diagnostic hint
yichao-liang May 6, 2026
1d939b0
Inject predicate signatures into synthesis kickoff message
yichao-liang May 6, 2026
edff828
Increase max retries for agent bilevel approach from 1 to 3 on refine…
yichao-liang May 6, 2026
2fd8942
Add roll to PyBullet robot type for lossless reset round-trip
yichao-liang May 6, 2026
62ff922
Populate roll feature in PyBullet task-init dicts
yichao-liang May 6, 2026
2806320
Surface mismatched features in state-reset reconstruction warning
yichao-liang May 6, 2026
c689b9c
Use asymmetric CHANGE_FINGERS terminal so OpenFingers actually opens
yichao-liang May 7, 2026
83a64cb
Loosen reset_state joint-vs-EE atol so fresh _get_state hints survive
yichao-liang May 7, 2026
222680d
Compare angle features modulo 2π in reconstruction diff
yichao-liang May 7, 2026
7a0dde2
Linearly interpolate finger state↔joint conversion
yichao-liang May 7, 2026
2776233
Swap agents.yaml back to agent_param_learning for boil debugging
yichao-liang May 7, 2026
bb2262e
Apply autoformatter reflows to neighboring code
yichao-liang May 7, 2026
4214979
Add subclass hooks for extending AgentSimLearningApproach synthesis
yichao-liang May 7, 2026
c860229
Add AgentSimPredicateInventionApproach with predicate-quality tool
yichao-liang May 7, 2026
e332b2d
Swap agents.yaml to agent_predicate_invention for boil
yichao-liang May 7, 2026
d8f2888
Add goal_nl on boil tasks and propagate through strip_task
yichao-liang May 8, 2026
5050853
Render goal_nl and trajectory provenance in agent-facing tool output
yichao-liang May 8, 2026
904f7c0
Drop env-goal mimicry; agent invents predicates freely with NL goal hint
yichao-liang May 8, 2026
45db760
Pass full trajectory history and goal-check helpers into synthesis
yichao-liang May 8, 2026
bb2b108
Fix async_generator pickle leak by decoupling _ParamsView from approach
yichao-liang May 8, 2026
f8c80cc
Enable online learning cycles by default; misc config tweaks
yichao-liang May 8, 2026
871acba
Tag agent log files by query kind instead of session manager
yichao-liang May 8, 2026
f402e91
Tag agent query call sites with phase kind
yichao-liang May 8, 2026
6dabc68
Show tqdm progress bar during backtracking refinement
yichao-liang May 8, 2026
2ffddfb
Enable online_learning_early_stopping in predicatorv3 agents config
yichao-liang May 8, 2026
662d686
Spill oversize run_python output to sandbox instead of ~/.claude
yichao-liang May 11, 2026
2b57865
Filter solve-prompt goal atoms by current predicate set
yichao-liang May 12, 2026
5c0dceb
Version sandbox artifacts by cycle and surface provenance to the agent
yichao-liang May 12, 2026
7a64ded
Add unit tests for sandbox versioning, provenance, and recent fixes
yichao-liang May 12, 2026
c5bc9f4
Apply autoformat and silence lint on touched files
yichao-liang May 12, 2026
063fcbd
Make reset_state fast-path sign-aware and tighten position tolerance
yichao-liang May 12, 2026
e5daecc
Use explorer's own rng in agent bilevel explorer
yichao-liang May 12, 2026
516703f
Add require_all_attempts mode for online-learning early stop
yichao-liang May 12, 2026
d30f86c
Pin env reference at construction in AgentPlannerApproach
yichao-liang May 12, 2026
1bfe39e
Extract _ArtifactSnapshotter from synthesis-tool factories
yichao-liang May 12, 2026
020697d
Split agent session tool surface into solve/synthesis phases
yichao-liang May 12, 2026
e546a15
Add logging for tool surface details in AgentSessionMixin
yichao-liang May 12, 2026
8e7c202
Fix CI failures: pylint, mypy, autoformat, and flaky MCMC test
yichao-liang May 12, 2026
84d596b
Drop strict happiness_speed assertion in MCMC fitting test
yichao-liang May 12, 2026
82a1551
Skip task in _demo_dataset_loading when solve fails and we discard fa…
yichao-liang May 12, 2026
fb3d0db
Add debug logging for final interaction state and abstract state in _…
yichao-liang May 13, 2026
8d57ec3
Tighten _object_pose_matches_state atol to 1e-3 to match _reconstruct…
yichao-liang May 13, 2026
24773a7
Make jug liquid visual-only and track jug pose each step
yichao-liang May 13, 2026
7d5eba8
Add regression test for SwitchBurnerOn/Waypoint_1 cup-collision
yichao-liang May 13, 2026
d096c73
Add end-to-end test that oracle_process_planning solves a boil task
yichao-liang May 13, 2026
ffd8855
Add refinement-vs-real-execution alignment test using synth simulator…
yichao-liang May 13, 2026
ea40dbf
Fix CI: autoformat, mypy, and pylint cleanups
yichao-liang May 13, 2026
bc9a037
Update samplers in processes.py to use random uniform values and remo…
yichao-liang May 13, 2026
3608211
Make sandbox system prompt and CLAUDE.md phase-aware
yichao-liang May 13, 2026
a2b7e54
Use counter-first log filenames for chronological sort
yichao-liang May 13, 2026
239cea9
Make model-learning prompts domain-general and add geometric-gates note
yichao-liang May 13, 2026
22d3f51
Log session tool surface one tool per line
yichao-liang May 13, 2026
29808d2
Force synthesis agent to pre-load all MCP tool schemas on turn 1
yichao-liang May 13, 2026
7a8ea11
Retry transient PyBullet shared-memory errors
yichao-liang May 13, 2026
41e3dc3
Revert "Force synthesis agent to pre-load all MCP tool schemas on tur…
yichao-liang May 13, 2026
1478d59
Refactor comments in online learning loop for clarity and conciseness
yichao-liang May 14, 2026
14cbf95
Make geometric-gate guidance binding in synthesis prompts
yichao-liang May 14, 2026
4310ad9
Log final state details in forward validation; sync fitted params to …
yichao-liang May 16, 2026
8d9b72e
Apply autoformat fixes across pybullet helpers and agent SDK files
yichao-liang May 17, 2026
3909370
Trust authoritative joint positions in robot reset_state
yichao-liang May 17, 2026
38c783d
Add --parallel mode and self-bootstrap sys.path in local launch scripts
yichao-liang May 17, 2026
1138d49
Drop unused INSPECTION_TOOL_NAMES import
yichao-liang May 17, 2026
ff5217d
Surface forward-validation failures in synthesis plan refinement
yichao-liang May 19, 2026
352aff2
Bump interaction-request step cap and run 5 seeds from 0
yichao-liang May 19, 2026
3fd741f
Apply autoformat and split long line in forward validator
yichao-liang May 19, 2026
8c30703
Add 'paper/' directory to .gitignore
yichao-liang May 20, 2026
3803aa4
Add agent_bilevel_max_refine_retries setting
yichao-liang May 20, 2026
d7e2ce5
Reseed bilevel refinement before re-querying the LLM in _solve
yichao-liang May 20, 2026
7a00278
Silence mypy unreachable warning for macOS-only launch scripts
yichao-liang May 20, 2026
364c9ce
Merge branch 'master' into sim-learning
yichao-liang May 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ predicators/datasets/vlm_input_data_prompts/vision_api/response.txt

# Jetbrains IDEs
.idea/

paper/
8 changes: 8 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ disallow_untyped_defs = True
[mypy-scripts.*]
disallow_untyped_defs = True

# macOS-only launch helpers: the `sys.platform != "darwin"` guard makes the
# rest of the function dead code under mypy's Linux (CI) platform analysis.
[mypy-scripts.local.launch]
warn_unreachable = False

[mypy-scripts.local.launch_simp]
warn_unreachable = False

[mypy-predicators.tests.*]
ignore_missing_imports = True

Expand Down
123 changes: 104 additions & 19 deletions predicators/agent_sdk/agent_session_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@
creation from AgentPlannerApproach and AgentAbstractionLearningApproach.
"""
import asyncio
import logging
import os
from typing import Any, Dict, List, Optional, Set, Union

from predicators.agent_sdk.session_manager import AgentSessionManager, \
run_query_sync
from predicators.agent_sdk.tools import ToolContext, create_mcp_tools, \
get_allowed_tool_list
from predicators.agent_sdk.tools import ALL_TOOL_NAMES, ToolContext, \
create_mcp_tools, get_allowed_tool_list
from predicators.explorers import create_explorer
from predicators.explorers.base_explorer import BaseExplorer
from predicators.settings import CFG
from predicators.structs import ParameterizedOption, Predicate, Task, Type

logger = logging.getLogger(__name__)


class AgentSessionMixin:
"""Mixin that provides shared agent session infrastructure.
Expand All @@ -25,7 +28,19 @@ class AgentSessionMixin:
- _get_agent_system_prompt()

And may optionally override:
- _get_agent_tool_names() -- subset of ALL_TOOL_NAMES (None = all)
- _get_solve_tool_names() -- complete tool surface for
solve / explore sessions. May mix static MCP tool names with
names of dynamic ``SdkMcpTool`` instances. ``None`` = all
static MCP tools, ``[]`` = none.
- _get_synthesis_tool_names() -- complete tool surface for
synthesis sessions (``_learning_mode=True``). Same shape /
semantics as the solve hook, independent value.

Dynamic ``SdkMcpTool`` instances are supplied by the approach
directly: it assigns them to ``ctx.extra_mcp_tools`` before
opening a synthesis session and clears the field afterwards. The
mixin asserts the instance names line up with the names declared
in :meth:`_get_synthesis_tool_names`.
"""

_log_subdir: str = "agent" # fallback; _get_log_dir prefers get_name()
Expand Down Expand Up @@ -60,13 +75,28 @@ def _get_agent_system_prompt(self) -> str:
"""Return the system prompt for the agent session."""
raise NotImplementedError

def _get_agent_tool_names(self) -> Optional[List[str]]:
"""Return tool name filter.
def _get_solve_tool_names(self) -> Optional[List[str]]:
"""Return the complete tool surface for solve / explore sessions.

None means all tools; override to subset.
May mix static MCP tool names with names of dynamic
``SdkMcpTool`` instances. ``None`` means "all static MCP tools";
override to subset.
"""
return None

def _get_synthesis_tool_names(self) -> Optional[List[str]]:
"""Return the complete tool surface for the synthesis session.

Selected when ``_learning_mode`` is True. Independent of the
solve list — the two phases may share names or be disjoint. Each
name must back either a static MCP tool (member of
``ALL_TOOL_NAMES``) or a dynamic ``SdkMcpTool`` instance the
approach attaches via ``ctx.extra_mcp_tools``. Default ``[]``
means no tools (approaches with no synthesis phase need not
override).
"""
return []

def _get_sandbox_reference_files(self) -> Dict[str, str]:
"""Return extra reference files for the docker sandbox.

Expand All @@ -92,7 +122,58 @@ def _ensure_agent_session(self) -> None:
if self._agent_session is not None:
return

tool_names = self._get_agent_tool_names() # pylint: disable=assignment-from-none
# Pick the declared tool surface by phase. ``_learning_mode`` is
# the same signal the system-prompt branch reads, so tools and
# prompt stay in sync. Each approach declares its solve and
# synthesis tool sets independently — they may be disjoint.
# ``tool_names`` is the *complete* declared list (may mix static
# MCP names with names of dynamic SdkMcpTool instances).
if getattr(self, "_learning_mode", False):
tool_names = self._get_synthesis_tool_names() # pylint: disable=assignment-from-none
else:
tool_names = self._get_solve_tool_names() # pylint: disable=assignment-from-none

# Sanity: every dynamic name in the declared list must have a
# backing tool attached to ``ctx.extra_mcp_tools``. Static MCP
# names (``ALL_TOOL_NAMES``) are excluded — they're materialized
# downstream by ``create_mcp_tools``. Catches typos and missing
# builder hooks before the agent silently fails to invoke a
# declared-but-missing tool.
declared = set(tool_names or ())
dynamic_declared = declared - set(ALL_TOOL_NAMES)
if dynamic_declared:
attached = list(self._tool_context.extra_mcp_tools or ())
built = {getattr(t, "name", "") for t in attached}
missing = dynamic_declared - built
phase_for_msg = ("synthesis" if getattr(self, "_learning_mode",
False) else "solve")
assert not missing, (
f"Dynamic tool name(s) {sorted(missing)} declared in "
f"_get_{phase_for_msg}_tool_names but no matching tool "
f"attached to ctx.extra_mcp_tools — add them to the "
f"builder or drop the names.")

phase = "synthesis" if getattr(self, "_learning_mode",
False) else "solve"
approach_name = getattr(type(self), "get_name",
lambda: type(self).__name__)()
if tool_names is None:
logger.info(
"[%s] %s session tool surface: ALL static MCP tools "
"(no subset declared).", approach_name, phase)
else:
static = sorted(n for n in tool_names if n in set(ALL_TOOL_NAMES))
dynamic = sorted(n for n in tool_names
if n not in set(ALL_TOOL_NAMES))
lines = [
f"[{approach_name}] {phase} session tool surface "
f"({len(tool_names)} total):"
]
for n in static:
lines.append(f" static {n}")
for n in dynamic:
lines.append(f" dynamic {n}")
logger.info("\n".join(lines))

if CFG.agent_sdk_use_docker_sandbox:
from predicators.agent_sdk.docker_sandbox import \
Expand All @@ -105,6 +186,7 @@ def _ensure_agent_session(self) -> None:
tool_names=tool_names,
image=CFG.agent_sdk_docker_image,
extra_reference_files=self._get_sandbox_reference_files(),
phase=phase,
)
elif CFG.agent_sdk_use_local_sandbox:
from predicators.agent_sdk.local_sandbox import \
Expand All @@ -116,6 +198,7 @@ def _ensure_agent_session(self) -> None:
tool_context=self._tool_context,
tool_names=tool_names,
extra_reference_files=self._get_sandbox_reference_files(),
phase=phase,
)
else:
from claude_agent_sdk import \
Expand All @@ -128,29 +211,26 @@ def _ensure_agent_session(self) -> None:
tools=tools,
)

extra_names = [
getattr(t, "name", "")
for t in self._tool_context.extra_mcp_tools
]
self._agent_session = AgentSessionManager(
system_prompt=self._get_agent_system_prompt(),
mcp_server=mcp_server,
log_dir=self._get_log_dir(),
model_name=CFG.agent_sdk_model_name,
allowed_tools=get_allowed_tool_list(tool_names,
extra_names=extra_names
or None),
allowed_tools=get_allowed_tool_list(tool_names),
tool_context=self._tool_context,
)

if self._agent_session_id is not None:
sess = self._agent_session
sess.session_id = ( # type: ignore[attr-defined,union-attr]
self._agent_session_id)

# Save system prompt to log directory
# Save system prompt to log directory. Suffix with the phase tag
# so solve and synthesis prompts don't overwrite each other across
# phase switches.
log_dir = self._get_log_dir()
os.makedirs(log_dir, exist_ok=True)
prompt_path = os.path.join(log_dir, "system_prompt.txt")
prompt_path = os.path.join(log_dir, f"system_prompt_{phase}.md")
with open(prompt_path, "w", encoding="utf-8") as f:
f.write(self._get_agent_system_prompt())

Expand Down Expand Up @@ -182,11 +262,16 @@ def _close_agent_session(self) -> None:
except Exception: # pylint: disable=broad-except
pass

def _query_agent_sync(self, message: str) -> List[Dict[str, Any]]:
"""Synchronous wrapper for async agent query."""
def _query_agent_sync(self, message: str,
**query_kwargs: Any) -> List[Dict[str, Any]]:
"""Synchronous wrapper for async agent query.

Extra kwargs (e.g. ``kind="learn"``) are forwarded to the
session's ``query`` method for log-file tagging.
"""
self._ensure_agent_session()
assert self._agent_session is not None
return run_query_sync(self._agent_session, message)
return run_query_sync(self._agent_session, message, **query_kwargs)

def _create_agent_explorer(
self,
Expand Down
Loading
Loading