Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
14e96f2
[AISOS-2298] Define Draft and Item Pydantic Models in src/forge/model…
ekuris-redhat Jul 30, 2026
f4026de
[AISOS-2299] Implement Jira API Attachment Helpers in JiraClient
ekuris-redhat Jul 30, 2026
ac4f0ad
[AISOS-2299] Fix concurrent request race condition in JiraClient atta…
ekuris-redhat Jul 30, 2026
5b1d20e
[AISOS-2300] Develop DraftManager in src/forge/workflow/utils/draft_m…
ekuris-redhat Jul 30, 2026
3e6bc0d
[AISOS-2301] Add unit tests for DraftManager
ekuris-redhat Jul 30, 2026
78b7931
[AISOS-2301] Add Unit Tests for DraftManager and simplify implementation
ekuris-redhat Jul 30, 2026
301ee06
[AISOS-2302] Implement Command Classification & Parameter Parsing in …
ekuris-redhat Jul 30, 2026
cd1023f
[AISOS-2302] Extract shared key-value pair parsing logic and update J…
ekuris-redhat Jul 30, 2026
f992777
[AISOS-2303] Implement Draft Mutation Logic in DraftManager
ekuris-redhat Jul 30, 2026
5594d68
[AISOS-2303] Implement Draft Mutation Logic and Refactor DraftManager…
ekuris-redhat Jul 30, 2026
8c18afd
[AISOS-2304] Implement Natural Language Revision LLM Chain in ForgeAgent
ekuris-redhat Jul 30, 2026
127e994
[AISOS-2305] Integrate Comment Commands and Rollback in Orchestrator …
ekuris-redhat Jul 30, 2026
7883d7c
[AISOS-2306] Integrate Draft Review Gate in Epic Decomposition Node
ekuris-redhat Jul 30, 2026
2632879
[AISOS-2307] Integrate Draft Review Gate in Task Generation Node
ekuris-redhat Jul 30, 2026
2553ed9
[AISOS-2308] Implement Draft-Based Ticket Provisioning on Approval
ekuris-redhat Jul 30, 2026
40a8565
[AISOS-2309] Integrate Comment Commands and Label Events in Orchestra…
ekuris-redhat Jul 30, 2026
0fd50d7
[AISOS-2310] Implement integration tests for draft review flow
ekuris-redhat Jul 30, 2026
ee58950
[AISOS-2294-review] Local code review — fix breaking issues
ekuris-redhat Jul 30, 2026
1934649
[AISOS-2294-docs] Update stale documentation for draft-based planning…
ekuris-redhat Jul 30, 2026
03f9b81
[AISOS-2294] review: address PR feedback
ekuris-redhat Jul 30, 2026
8a0ebf9
[AISOS-2294-review-fix] Implement PR review plan for AISOS-2294
ekuris-redhat Jul 30, 2026
6aa93f9
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Jul 30, 2026
8095baa
[AISOS-2294] review: address PR feedback
ekuris-redhat Jul 30, 2026
bd6f8cd
[AISOS-2294-review-fix] Implement PR review plan for AISOS-2294
ekuris-redhat Jul 30, 2026
eb9a76c
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Jul 30, 2026
3d3295a
[AISOS-2294] review: address PR feedback
ekuris-redhat Jul 30, 2026
a36bced
[AISOS-2294-review-fix] Implement PR review plan for AISOS-2294
ekuris-redhat Jul 30, 2026
568b1f4
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Jul 30, 2026
c561bf8
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Jul 30, 2026
57200d0
[AISOS-2294-review-analyze] Analyze PR review feedback for AISOS-2294
ekuris-redhat Jul 30, 2026
49b674c
[AISOS-2294] review: address PR feedback
ekuris-redhat Jul 30, 2026
869bf68
[AISOS-2294-review-review-impl] Fix draft review flow integration tes…
ekuris-redhat Jul 30, 2026
ea0476e
[AISOS-2294-review-analyze] Analyze PR review feedback for AISOS-2294
ekuris-redhat Jul 30, 2026
b86a317
[AISOS-2294] review: address PR feedback
ekuris-redhat Jul 30, 2026
7c4e43e
[AISOS-2294-review-review-impl] Refine typing signature of check_yolo…
ekuris-redhat Jul 30, 2026
a8c7b4b
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Jul 30, 2026
b4fee42
[AISOS-2294-review-fix] review: address PR feedback
ekuris-redhat Aug 2, 2026
5201166
[AISOS-2294-review-review-impl] Post-review-impl code review and robu…
ekuris-redhat Aug 2, 2026
4169170
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Aug 2, 2026
d3940f5
[AISOS-2294-review-review-impl] Fix legacy workflow execution integra…
ekuris-redhat Aug 2, 2026
8362826
[AISOS-2294-review-fix] Address PR feedback for AISOS-2294
ekuris-redhat Aug 2, 2026
f84b475
[AISOS-2294-review-analyze] Analyze PR review feedback for AISOS-2294
ekuris-redhat Aug 2, 2026
f6042b4
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 2, 2026
3bf9e72
[AISOS-2294-review-review-impl] Post-implementation code review and c…
ekuris-redhat Aug 2, 2026
620682c
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Aug 2, 2026
849eff8
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 3, 2026
553c4fe
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Aug 3, 2026
23f4350
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 3, 2026
bf1f097
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 3, 2026
2f2d106
[AISOS-2294-review-review-impl] Fix container entrypoint sandbox test…
ekuris-redhat Aug 3, 2026
97ce16f
[AISOS-2294-rebase] Resolve merge conflicts with main for AISOS-2294
ekuris-redhat Aug 3, 2026
de7cca0
[AISOS-2294-ci-fix] Apply CI fix plan (attempt 1)
ekuris-redhat Aug 3, 2026
d3a7182
[AISOS-2294-review-ci-fix-1] Run post-ci-fix-1 code review and format…
ekuris-redhat Aug 3, 2026
211d5e5
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 3, 2026
f37ede7
[AISOS-2294-review-review-impl] Resolve breaking build, import and ty…
ekuris-redhat Aug 3, 2026
94d07bb
[AISOS-2294-review-fix] Brief summary of what was implemented
ekuris-redhat Aug 4, 2026
deef8b2
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 4, 2026
714bf13
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 4, 2026
bce4cad
[AISOS-2294-rebase] Resolve merge conflicts with main for AISOS-2294
ekuris-redhat Aug 5, 2026
d44397c
[AISOS-2294-rebase] Resolve merge conflicts with main for AISOS-2294
ekuris-redhat Aug 5, 2026
2a9e875
[AISOS-2294-rebase] Resolve merge conflicts with main for AISOS-2294
ekuris-redhat Aug 6, 2026
bfaa64a
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 6, 2026
71b6eab
[AISOS-2294-review-review-impl] Clean up and verify post-review imple…
ekuris-redhat Aug 6, 2026
e79f3da
[AISOS-2294-review-review-impl] Fix sandbox runner test mock issue wi…
ekuris-redhat Aug 6, 2026
e331eaa
[AISOS-2294-rebase] Resolve merge conflicts with main for AISOS-2294
ekuris-redhat Aug 9, 2026
5e3bc28
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 9, 2026
7128369
[AISOS-2294] review: address PR feedback
ekuris-redhat Aug 11, 2026
f6d6deb
[AISOS-2294-review-fix] Implement PR review plan for AISOS-2294
ekuris-redhat Aug 11, 2026
85336cf
[AISOS-2294-review-fix] Remove .mypy_cache/ directory from Git tracking
ekuris-redhat Aug 11, 2026
5c99a9b
[AISOS-2294-review-fix] Implement PR review plan for AISOS-2294
ekuris-redhat Aug 11, 2026
5066f08
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Aug 11, 2026
27dd0e8
[AISOS-2294-review-review-impl] Fix mypy type check warnings and rede…
ekuris-redhat Aug 11, 2026
5556de5
[AISOS-2294-review-fix] [AISOS-2294] review: address PR feedback
ekuris-redhat Aug 11, 2026
204703c
[AISOS-2294-review-fix] Implement PR review plan for AISOS-2294
ekuris-redhat Aug 11, 2026
7e7b243
[AISOS-2294-review-review-impl] Post-review-impl code review
ekuris-redhat Aug 11, 2026
9b9a837
[AISOS-2294-review-review-impl] Add WorkflowState typing casts in pla…
ekuris-redhat Aug 11, 2026
41b24ba
[AISOS-2294-review-fix] [AISOS-2294] review: address PR feedback
ekuris-redhat Aug 11, 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
11 changes: 8 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,16 @@ podman rm $(podman ps -a --filter name=forge- -q)

## Jira Comment Syntax

| Prefix | Effect |
|--------|--------|
| `!` | Revision request — triggers regeneration with feedback |
| Prefix / Command | Effect |
|------------------|--------|
| `!` | Revision request — triggers regeneration/revision with feedback |
| `?` or `@forge ask` | Question — triggers Q&A answer |
| `>option N` | RCA option selection (RCA Option Gate only) |
| `/forge approve` | Approve draft (Epic plan or Tasks) to provision tickets |
| `/forge remove ID` | Remove proposed draft item by ID and re-sequence |
| `/forge exclude ID` | Toggle exclusion of proposed draft item by ID |
| `/forge update ID key=val` | Update fields (`summary`, `description`, `repo`) of proposed draft item |
| `/forge add key=val` | Add a new proposed item to draft |
| _(no prefix)_ | Informational — workflow ignores it |

## GitHub PR Comment Commands
Expand Down
12 changes: 12 additions & 0 deletions docs/developer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,18 @@ curl -X POST http://localhost:8000/api/v1/webhooks/github \
| `/forge skip-gate <name>` | Skip named CI check | CI stages |
| `/forge unskip-gate <name>` | Remove a skip | CI stages |

### Jira comment commands

These commands are used on the parent Jira ticket during the draft review stages (Epic Plan and Tasks).

| Command | Effect | Active at |
|---------|--------|-----------|
| `/forge approve` | Approve draft, provision sub-tickets, and delete draft attachment | `plan_approval_gate`, `task_approval_gate` |
| `/forge remove <ID>` | Remove a draft item by local sequential ID | `plan_approval_gate`, `task_approval_gate` |
| `/forge exclude <ID>` | Toggle the exclusion flag of a draft item | `plan_approval_gate`, `task_approval_gate` |
| `/forge update <ID> key=val` | Update fields (`summary`, `description`, `repo`) of a draft item | `plan_approval_gate`, `task_approval_gate` |
| `/forge add key=val` | Add a new proposed item to the draft | `plan_approval_gate`, `task_approval_gate` |

### Jira labels

| Label | Meaning |
Expand Down
54 changes: 36 additions & 18 deletions docs/guide/feature-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,31 @@ Forge generates a behavioral specification from the approved PRD, typically usin

Forge breaks the feature into logical epics — high-level areas of work that map to implementation phases.

**Human action:** Review the epic plan. You have four options at this stage:
By default, Forge uses an interactive **Draft Review Flow** at this stage (unless YOLO mode is active):
1. Instead of creating Jira tickets immediately, Forge serializes the proposed epics into `forge-stories-draft.json` and uploads it as an attachment on the Feature ticket.
2. Forge posts a markdown table comment on the Feature ticket outlining the proposed Epics.
3. The workflow pauses at `plan_approval_gate`.

| Action | How |
|--------|-----|
| Approve | Change label to `forge:plan-approved` |
| Ask a question | Comment with `?` prefix — Forge answers without re-decomposing |
| Revise one epic | `!` comment on the **specific epic sub-ticket** — Forge updates only that epic |
| Redo the full decomposition | `!` comment on the **feature ticket** — Forge regenerates all epics with your feedback |
**Human action:** Review the epic plan draft. You have several options at this stage:

| Action | How | Description |
|--------|-----|-------------|
| **Approve** | Comment `/forge approve` OR set label to `forge:plan-approved` | Forge provisions the Epic sub-tickets on Jira from the draft, deletes the draft attachment, and advances to Task Generation. |
| **Direct Edit** | Use `/forge` commands (e.g. `/forge update`, `/forge remove`, etc.) | Directly modify the draft attachment and regenerate the proposal comment. See [Jira Labels & Comments](labels.md) for a list of commands. |
| **Ask a question** | Comment with `?` prefix or `@forge ask` | Forge answers your question without regenerating the draft. |
| **Request revisions** | Comment with `!` prefix followed by your feedback | Forge uses LLM assistance to revise the entire draft JSON and update the proposal comment with your feedback. |

If `forge:yolo` mode is active, the draft review is bypassed. Epics are created in Jira immediately, and the workflow automatically proceeds to Task Generation.

If `forge:direct-mode` is active, the draft review is also bypassed and Epics are created in Jira immediately, but the workflow still pauses at the `plan_approval_gate` waiting for manual human approval (via label or commands) before proceeding.

```mermaid
flowchart TD
Gate([plan_approval_gate])
Gate -->|forge:plan-approved| Next[Generate Tasks]
Gate -->|forge:plan-approved or /forge approve| Next[Generate Tasks]
Gate -->|"? on feature ticket"| QA[Answer Question]
Gate -->|"! on feature ticket"| Regen[Regenerate All Epics]
Gate -->|"! on epic sub-ticket"| Update[Update Single Epic]
Gate -->|"/forge update/remove/exclude/add"| Update[Modify Draft]
QA --> Gate
Regen --> Gate
Update --> Gate
Expand All @@ -93,22 +102,31 @@ flowchart TD

Forge generates granular implementation tasks scoped to individual repositories. Each task is sized to fit in a single container execution pass.

**Human action:** Review the tasks. You have four options at this stage:
By default, Forge uses an interactive **Draft Review Flow** at this stage (unless YOLO mode is active):
1. Instead of creating Jira tickets immediately, Forge serializes the proposed tasks into `forge-tasks-draft.json` and uploads it as an attachment on the Feature ticket.
2. Forge posts a markdown table comment on the Feature ticket outlining the proposed Tasks.
3. The workflow pauses at `task_approval_gate`.

**Human action:** Review the task draft. You have several options at this stage:

| Action | How | Description |
|--------|-----|-------------|
| **Approve** | Comment `/forge approve` OR set label to `forge:task-approved` | Forge provisions the Task sub-tickets on Jira from the draft, deletes the draft attachment, and advances to Implementation. |
| **Direct Edit** | Use `/forge` commands (e.g. `/forge update`, `/forge remove`, etc.) | Directly modify the draft attachment and regenerate the proposal comment. See [Jira Labels & Comments](labels.md) for a list of commands. |
| **Ask a question** | Comment with `?` prefix or `@forge ask` | Forge answers your question without regenerating the draft. |
| **Request revisions** | Comment with `!` prefix followed by your feedback | Forge uses LLM assistance to revise the entire draft JSON and update the proposal comment with your feedback. |

If `forge:yolo` mode is active, the draft review is bypassed. Tasks are created in Jira immediately, and the workflow automatically proceeds to Implementation.

| Action | How |
|--------|-----|
| Approve | Change label to `forge:task-approved` |
| Ask a question | Comment with `?` prefix — Forge answers without regenerating |
| Revise one task | `!` comment on the **specific task sub-ticket** — Forge updates only that task |
| Regenerate all tasks | `!` comment on the **feature or epic ticket** — Forge regenerates the full task list with your feedback |
If `forge:direct-mode` is active, the draft review is also bypassed and Tasks are created in Jira immediately, but the workflow still pauses at the `task_approval_gate` waiting for manual human approval (via label or commands) before proceeding.

```mermaid
flowchart TD
Gate([task_approval_gate])
Gate -->|forge:task-approved| Next[Implement Tasks]
Gate -->|forge:task-approved or /forge approve| Next[Implement Tasks]
Gate -->|"? on ticket"| QA[Answer Question]
Gate -->|"! on feature/epic"| Regen[Regenerate All Tasks]
Gate -->|"! on task sub-ticket"| Update[Update Single Task]
Gate -->|"/forge update/remove/exclude/add"| Update[Modify Draft]
QA --> Gate
Regen --> Gate
Update --> Gate
Expand Down
29 changes: 25 additions & 4 deletions docs/guide/labels.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,40 @@ Standalone Tasks and Epics can be processed with the standard `forge:managed` la
| `forge:blocked` | Set by Forge when a stage fails. Forge posts a comment with the error. |
| `forge:retry` | Add this to resume from the exact node that failed, or to transition from `review_response_gate` back to `human_review_gate` (clearing contested review comments). Forge removes it after resuming. |
| `forge:yolo` | Auto-approve supported planning gates. Human PR review still remains a gate. |
| `forge:direct-mode` | Direct ticket creation mode (bypasses draft JSON attachments and creates Epic/Task tickets immediately in Jira), but still pauses for human approval at the planning gates (instead of auto-approving like `forge:yolo`). |
| `repo:<owner>/<repo>` | Identifies repositories selected for planning and implementation. |

## How to Use Labels

**Starting a workflow:** Create a Jira issue and add `forge:managed`. Forge detects the issue type and begins the appropriate pipeline: Feature/Story, Bug, or standalone Task/Epic takeover.

**Approving a stage:** When Forge posts a PRD, spec, or other artifact, it sets the `forge:*-pending` label. Change it to `forge:*-approved` to advance the workflow. Do not add the approved label manually before Forge posts — it won't be recognized until the pending state is set.
**Approving a stage:** When Forge posts an artifact (such as a PRD or Spec), it sets the `forge:*-pending` label. You can approve it by changing the label to `forge:*-approved` to advance the workflow. For draft-based stages (Epic Plan and Tasks), you can also approve by commenting `/forge approve` on the ticket.

**Requesting revisions:** Start a comment with `!` followed by your feedback. Forge regenerates the artifact and resets the pending label.
**Interactive Draft Review:** For Epic Decomposition and Task Generation stages, Forge uses a draft-based review flow by default (unless `forge:yolo` or `forge:direct-mode` mode is active).
1. Instead of creating sub-tickets immediately, Forge serializes the proposed items into a JSON draft file (`forge-stories-draft.json` or `forge-tasks-draft.json`) and uploads it as a Jira attachment.
2. Forge posts a formatted markdown table comment on the ticket detailing the proposed plan.
3. While the stage is pending, you can modify the draft directly using **Jira comment commands** (see below) or request a natural language revision.
4. Once you approve (via `/forge approve` or setting the approved label), Forge downloads the draft, provisions the actual Jira tickets from it, and deletes the draft attachment.

**Asking questions:** Start a comment with `?` or `@forge ask`. Forge answers without advancing or regenerating.
### Jira Comment Commands

**Informational comments:** Comments without a recognized prefix (`!`, `?`, `@forge ask`, `>option`) are ignored by the workflow — use them for team discussion without triggering Forge.
For stages using the draft-based review flow (Epic Plan and Tasks), you can post comments on the parent ticket with the following commands:

| Command | Description | Example |
|---------|-------------|---------|
| `/forge approve` | Approve the draft, provision all non-excluded items as Jira tickets, and delete the draft attachment. | `/forge approve` |
| `/forge remove <ID>` | Remove a draft item by its local sequential ID. Remaining items are automatically re-sequenced. | `/forge remove 3` |
| `/forge exclude <ID>` | Toggle the exclusion flag of a draft item. Excluded items are skipped during ticket provisioning. | `/forge exclude 2` |
| `/forge update <ID> key=val` | Update fields of a draft item (supported keys: `summary`, `description`, `repo`). | `/forge update 1 repo="my-org/custom-repo"` |
| `/forge add key=val` | Add a new proposed item to the draft. | `/forge add summary="New Story" repo="my-org/repo"` |

*Note: Successful command/revision comments are automatically edited by Forge to prepend `✅`. If a command or revision fails, Forge posts a comment detailing the error with a leading `❌`.*

**Requesting revisions:** Start a comment with `!` followed by your feedback (e.g., `! update the repositories to use the new service`). For standard artifacts, Forge regenerates them. For drafts, Forge uses LLM assistance to revise the draft JSON attachment and update the proposed plan table.

**Asking questions:** Start a comment with `?` or `@forge ask`. Forge answers without advancing or regenerating/modifying the drafts.

**Informational comments:** Comments without a recognized prefix (such as `!`, `?`, `@forge ask`, `>option`, or `/forge`) are ignored by the workflow — use them for team discussion without triggering Forge.

**Handling failures:** When `forge:blocked` appears, read the Forge comment for the error. Fix the underlying issue if needed, then add `forge:retry`.

Expand Down
5 changes: 5 additions & 0 deletions src/forge/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,11 @@ def ignored_ci_checks(self) -> list[str]:
default=0.5, description="Webhook acknowledgment timeout in seconds"
)

yolo_mode: bool = Field(
default=False,
description="Autonomous mode - skip all artifact approval gates",
)

# Container Configuration
container_image: str = Field(
default="localhost/forge-dev:latest",
Expand Down
82 changes: 82 additions & 0 deletions src/forge/integrations/agents/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,88 @@ async def answer_question(
logger.info(f"Generated answer ({len(result)} chars)")
return result.strip() if result else ""

async def revise_draft_with_feedback(
self,
draft_content: str,
feedback: str,
context: dict[str, Any] | None = None,
) -> str:
"""Revise draft content based on user feedback.

Uses the 'revision-draft' prompt template to guide the LLM to output
the revised draft JSON.

Args:
draft_content: The current draft JSON content.
feedback: Natural language feedback.
context: Optional context from the workflow state.

Returns:
The updated draft JSON string.
"""
from langchain_core.output_parsers import StrOutputParser

# Format context into a readable string/JSON
context_str = json.dumps(context, indent=2) if context else "None provided"

# Load the prompt template using project's load_prompt
prompt_text = load_prompt(
"revision-draft",
draft_content=draft_content,
feedback=feedback,
context=context_str,
)

model = self._create_model()
chain = model | StrOutputParser()

logger.info("Revising draft using direct LangChain model chain")
response = await chain.ainvoke(prompt_text)

# Strip preamble/narration and validate as JSON
cleaned_text = response.strip()

# Check markdown code blocks first
pattern = r"```(?:json)?\s*([\s\S]*?)\s*```"
match = re.search(pattern, cleaned_text)
if match:
cleaned_text = match.group(1).strip()
else:
# If no code block, look for the JSON object/list boundary
# Find the first occurrence of '{' or '[' and the last of '}' or ']'
start_brace = cleaned_text.find("{")
start_bracket = cleaned_text.find("[")

# Determine which starts first
start_idx = -1
if start_brace != -1 and start_bracket != -1:
start_idx = min(start_brace, start_bracket)
elif start_brace != -1:
start_idx = start_brace
elif start_bracket != -1:
start_idx = start_bracket

if start_idx != -1:
# Find the last brace or bracket matching the start type
if start_idx == start_brace:
end_idx = cleaned_text.rfind("}")
else:
end_idx = cleaned_text.rfind("]")

if end_idx > start_idx:
cleaned_text = cleaned_text[start_idx : end_idx + 1].strip()

try:
parsed_json = json.loads(cleaned_text)
validated_json_str = json.dumps(parsed_json, indent=2)
logger.info(
f"Successfully revised draft and validated JSON ({len(validated_json_str)} chars)"
)
return validated_json_str
except json.JSONDecodeError as e:
logger.error(f"Failed to parse LLM response as valid JSON: {e}\nResponse: {response}")
raise ValueError(f"Failed to parse revised draft as JSON: {e}")

async def close(self) -> None:
"""Close the agent and cleanup resources."""
pass
Loading
Loading