idle-draft: per-work-type allowed_tools; research must web-search for stories
Research and topic_ideas runs get --allowedTools WebSearch,WebFetch; research template mandates >=1 web search for related stories with full-URL + access-date citations under the dossier's status labels. Claude-Session: https://claude.ai/code/session_01YQDoWNM7XPPii28khFWoMc
This commit is contained in:
@@ -223,6 +223,10 @@ def load_config(path: Path) -> dict:
|
||||
for wtype, wcfg in data["work_types"].items():
|
||||
if "providers" not in wcfg or not isinstance(wcfg["providers"], list):
|
||||
raise ConfigError(f"work_type '{wtype}' missing 'providers' list")
|
||||
if "allowed_tools" in wcfg:
|
||||
at = wcfg["allowed_tools"]
|
||||
if not isinstance(at, list) or not all(isinstance(x, str) for x in at):
|
||||
raise ConfigError(f"work_type '{wtype}' 'allowed_tools' must be a list of strings")
|
||||
return data
|
||||
|
||||
|
||||
@@ -749,12 +753,16 @@ def validate_output(work_type: str, text: str) -> tuple[bool, str]:
|
||||
# === Claude argv / execution ===
|
||||
|
||||
|
||||
def build_claude_argv(model_id: str | None, max_turns: int, add_dirs: list[str]) -> list[str]:
|
||||
def build_claude_argv(
|
||||
model_id: str | None, max_turns: int, add_dirs: list[str], allowed_tools: list[str] | None = None
|
||||
) -> list[str]:
|
||||
argv = ["claude", "-p", "--max-turns", str(max_turns)]
|
||||
if model_id:
|
||||
argv += ["--model", model_id]
|
||||
for d in add_dirs:
|
||||
argv += ["--add-dir", d]
|
||||
if allowed_tools:
|
||||
argv += ["--allowedTools", ",".join(allowed_tools)]
|
||||
return argv
|
||||
|
||||
|
||||
@@ -801,6 +809,14 @@ def resolve_add_dirs(config: dict, work_type: str) -> list[str]:
|
||||
return []
|
||||
|
||||
|
||||
def resolve_allowed_tools(config: dict, work_type: str) -> list[str]:
|
||||
"""Tool names granted to the headless child via --allowedTools, from
|
||||
config["work_types"][work_type]["allowed_tools"]. Empty/absent -> []
|
||||
(caller omits the flag; headless runs cannot answer permission prompts,
|
||||
so only tools explicitly listed here are usable by that work type)."""
|
||||
return list(config["work_types"].get(work_type, {}).get("allowed_tools") or [])
|
||||
|
||||
|
||||
def dispatch_preview(repo: Path, config: dict, candidate: dict, max_turns: int) -> dict:
|
||||
"""Compute everything a dryrun needs to print, without executing anything."""
|
||||
dossier = candidate["dossier"]
|
||||
@@ -809,7 +825,8 @@ def dispatch_preview(repo: Path, config: dict, candidate: dict, max_turns: int)
|
||||
profile_dir = expand(config["providers"][provider]["profile"])
|
||||
model_id = resolve_model_id(profile_dir)
|
||||
add_dirs = resolve_add_dirs(config, work_type)
|
||||
argv = build_claude_argv(model_id, max_turns, add_dirs)
|
||||
allowed_tools = resolve_allowed_tools(config, work_type)
|
||||
argv = build_claude_argv(model_id, max_turns, add_dirs, allowed_tools)
|
||||
canonical = canonical_output_path(repo, candidate)
|
||||
tmp_path = canonical.with_name(canonical.name + ".tmp")
|
||||
parsed_env = parse_provider_env(profile_dir / "provider.env")
|
||||
@@ -847,7 +864,8 @@ def run_task(repo: Path, config: dict, candidate: dict, max_turns: int, task_tim
|
||||
profile_dir = expand(config["providers"][provider]["profile"])
|
||||
model_id = resolve_model_id(profile_dir)
|
||||
add_dirs = resolve_add_dirs(config, work_type)
|
||||
argv = build_claude_argv(model_id, max_turns, add_dirs)
|
||||
allowed_tools = resolve_allowed_tools(config, work_type)
|
||||
argv = build_claude_argv(model_id, max_turns, add_dirs, allowed_tools)
|
||||
env = build_child_env(profile_dir)
|
||||
|
||||
timed_out = False
|
||||
|
||||
Reference in New Issue
Block a user