Add permission-aware follow-up flow with interactive resolution
When follow-up agent detects permission-blocked items ("ручное
применение", "permission denied", etc.), they become pending_actions
instead of auto-created tasks. User chooses per item:
1. Rerun with --dangerously-skip-permissions
2. Create manual task
3. Skip
core/followup.py:
_is_permission_blocked() — regex detection of 9 permission patterns
generate_followups() returns {created, pending_actions}
resolve_pending_action() — handles rerun/manual_task/skip
agents/runner.py:
_run_claude(allow_write=True) adds --dangerously-skip-permissions
run_agent/run_pipeline pass allow_write through
CLI: kin approve --followup — interactive 1/2/3 prompt per blocked item
API: POST /approve returns {needs_decision, pending_actions}
POST /resolve resolves individual actions
Frontend: pending actions shown as cards with 3 buttons in approve modal
136 tests, all passing. Frontend builds clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9264415776
commit
ab693d3c4d
7 changed files with 356 additions and 73 deletions
|
|
@ -23,6 +23,7 @@ def run_agent(
|
|||
previous_output: str | None = None,
|
||||
brief_override: str | None = None,
|
||||
dry_run: bool = False,
|
||||
allow_write: bool = False,
|
||||
) -> dict:
|
||||
"""Run a single Claude Code agent as a subprocess.
|
||||
|
||||
|
|
@ -62,7 +63,8 @@ def run_agent(
|
|||
|
||||
# Run claude subprocess
|
||||
start = time.monotonic()
|
||||
result = _run_claude(prompt, model=model, working_dir=working_dir)
|
||||
result = _run_claude(prompt, model=model, working_dir=working_dir,
|
||||
allow_write=allow_write)
|
||||
duration = int(time.monotonic() - start)
|
||||
|
||||
# Parse output — ensure output_text is always a string for DB storage
|
||||
|
|
@ -106,6 +108,7 @@ def _run_claude(
|
|||
prompt: str,
|
||||
model: str = "sonnet",
|
||||
working_dir: str | None = None,
|
||||
allow_write: bool = False,
|
||||
) -> dict:
|
||||
"""Execute claude CLI as subprocess. Returns dict with output, returncode, etc."""
|
||||
cmd = [
|
||||
|
|
@ -114,6 +117,8 @@ def _run_claude(
|
|||
"--output-format", "json",
|
||||
"--model", model,
|
||||
]
|
||||
if allow_write:
|
||||
cmd.append("--dangerously-skip-permissions")
|
||||
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
|
|
@ -207,6 +212,7 @@ def run_pipeline(
|
|||
task_id: str,
|
||||
steps: list[dict],
|
||||
dry_run: bool = False,
|
||||
allow_write: bool = False,
|
||||
) -> dict:
|
||||
"""Execute a multi-step pipeline of agents.
|
||||
|
||||
|
|
@ -253,6 +259,7 @@ def run_pipeline(
|
|||
previous_output=previous_output,
|
||||
brief_override=brief,
|
||||
dry_run=dry_run,
|
||||
allow_write=allow_write,
|
||||
)
|
||||
results.append(result)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue