Increase CLI timeout to 15min, fix result file reprocessing, and save outlines directly
- Bump Claude Code subprocess timeout from 5 to 15 minutes for longer content tasks - Fix scheduler result file loop: unlink source if already exists in processed/ dir - Pass outline save path to execution brain so it writes directly to network share Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>fix/customer-field-migration
parent
af67ae166d
commit
8f2ec48e10
|
|
@ -218,10 +218,10 @@ class LLMAdapter:
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
stdout, stderr = proc.communicate(input=prompt, timeout=300)
|
stdout, stderr = proc.communicate(input=prompt, timeout=900)
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
proc.kill()
|
proc.kill()
|
||||||
return "Error: Claude Code execution timed out after 5 minutes."
|
return "Error: Claude Code execution timed out after 15 minutes."
|
||||||
|
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
return f"Execution error: {stderr or 'unknown error'}"
|
return f"Execution error: {stderr or 'unknown error'}"
|
||||||
|
|
|
||||||
|
|
@ -653,6 +653,9 @@ class Scheduler:
|
||||||
result_path.rename(processed_dir / result_path.name)
|
result_path.rename(processed_dir / result_path.name)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
log.warning("Could not move result file %s: %s", result_path.name, e)
|
log.warning("Could not move result file %s: %s", result_path.name, e)
|
||||||
|
# If it already exists in processed/, delete the source to stop reprocessing
|
||||||
|
if (processed_dir / result_path.name).exists():
|
||||||
|
result_path.unlink(missing_ok=True)
|
||||||
|
|
||||||
# ── Folder Watcher ──
|
# ── Folder Watcher ──
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,7 @@ def _build_phase1_prompt(
|
||||||
cora_path: str,
|
cora_path: str,
|
||||||
capabilities_default: str,
|
capabilities_default: str,
|
||||||
is_service_page: bool = False,
|
is_service_page: bool = False,
|
||||||
|
outline_save_path: str = "",
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Build the Phase 1 prompt that triggers the content-researcher skill.
|
"""Build the Phase 1 prompt that triggers the content-researcher skill.
|
||||||
|
|
||||||
|
|
@ -286,6 +287,15 @@ def _build_phase1_prompt(
|
||||||
f'\nWhen asked about company capabilities, respond with: "{capabilities_default}"'
|
f'\nWhen asked about company capabilities, respond with: "{capabilities_default}"'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if outline_save_path:
|
||||||
|
parts.append(
|
||||||
|
f"\nSave the finished outline to `{outline_save_path}`. "
|
||||||
|
"Create any missing directories first. "
|
||||||
|
"The outline must be a complete markdown document with sections, "
|
||||||
|
"headings, entity targets, and keyword placement notes. "
|
||||||
|
"Do NOT save it anywhere else."
|
||||||
|
)
|
||||||
|
else:
|
||||||
parts.append(
|
parts.append(
|
||||||
"\nDeliver the outline as a complete markdown document with sections, "
|
"\nDeliver the outline as a complete markdown document with sections, "
|
||||||
"headings, entity targets, and keyword placement notes."
|
"headings, entity targets, and keyword placement notes."
|
||||||
|
|
@ -847,12 +857,29 @@ def _run_phase1(
|
||||||
capabilities_default: str,
|
capabilities_default: str,
|
||||||
is_service_page: bool = False,
|
is_service_page: bool = False,
|
||||||
) -> str:
|
) -> str:
|
||||||
|
# Compute the outline save path upfront so the execution brain writes
|
||||||
|
# directly to the network share (or local fallback).
|
||||||
|
slug = _slugify(keyword) or "unknown"
|
||||||
|
outline_path = ""
|
||||||
|
if config.content.outline_dir:
|
||||||
|
primary = Path(config.content.outline_dir) / slug
|
||||||
|
try:
|
||||||
|
primary.mkdir(parents=True, exist_ok=True)
|
||||||
|
outline_path = str(primary / "outline.md")
|
||||||
|
except OSError as e:
|
||||||
|
log.warning("Network path unavailable (%s), falling back to local: %s", primary, e)
|
||||||
|
if not outline_path:
|
||||||
|
local = _LOCAL_CONTENT_DIR / slug
|
||||||
|
local.mkdir(parents=True, exist_ok=True)
|
||||||
|
outline_path = str(local / "outline.md")
|
||||||
|
|
||||||
# ClickUp: move to automation underway
|
# ClickUp: move to automation underway
|
||||||
if task_id:
|
if task_id:
|
||||||
_sync_clickup_start(ctx, task_id)
|
_sync_clickup_start(ctx, task_id)
|
||||||
|
|
||||||
prompt = _build_phase1_prompt(
|
prompt = _build_phase1_prompt(
|
||||||
url, keyword, content_type, cora_path, capabilities_default, is_service_page
|
url, keyword, content_type, cora_path, capabilities_default, is_service_page,
|
||||||
|
outline_save_path=outline_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
log.info("Phase 1 — researching + outlining for '%s' (%s)", keyword, url or "new content")
|
log.info("Phase 1 — researching + outlining for '%s' (%s)", keyword, url or "new content")
|
||||||
|
|
@ -874,8 +901,15 @@ def _run_phase1(
|
||||||
_sync_clickup_fail(ctx, task_id, result)
|
_sync_clickup_fail(ctx, task_id, result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Save the outline
|
# Verify the outline was saved by the execution brain
|
||||||
outline_path = _save_content(result, keyword, "outline.md", config)
|
if not Path(outline_path).is_file():
|
||||||
|
log.warning(
|
||||||
|
"Execution brain did not save outline to %s; saving result text as fallback.",
|
||||||
|
outline_path,
|
||||||
|
)
|
||||||
|
Path(outline_path).parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
Path(outline_path).write_text(result, encoding="utf-8")
|
||||||
|
|
||||||
log.info("Outline saved to: %s", outline_path)
|
log.info("Outline saved to: %s", outline_path)
|
||||||
|
|
||||||
# ClickUp: move to outline review + store OutlinePath
|
# ClickUp: move to outline review + store OutlinePath
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue