Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 1 addition & 3 deletions src/iac_code/a2a/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1731,9 +1731,7 @@ def _resolve_cwd(self, metadata: Any | None) -> str:
raise ValueError("Invalid A2A workspace metadata.")
logical_cwd = os.path.normpath(cwd)
resolved_cwd = resolve_workspace_path(Path(logical_cwd))
if not trust_request_cwd() and not any(
_is_relative_to(resolved_cwd, root) for root in _allowed_cwd_roots()
):
if not trust_request_cwd() and not any(_is_relative_to(resolved_cwd, root) for root in _allowed_cwd_roots()):
raise ValueError("Invalid A2A workspace metadata.")
if resolved_cwd.exists():
if not resolved_cwd.is_dir():
Expand Down
26 changes: 8 additions & 18 deletions src/iac_code/a2a/input_required.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,35 +178,29 @@ def permission_display_fields(request: PermissionRequestEvent, *, language: str
command = safe_input.get("command") or safe_input.get("cmd")
if isinstance(command, str) and command.strip():
command_fallback = translate_message("shell command", language=language)
target = translate_message(
"the current local workspace; command: {command}", language=language
).format(command=_display_text(command, fallback=command_fallback, maximum=240))
target = translate_message("the current local workspace; command: {command}", language=language).format(
command=_display_text(command, fallback=command_fallback, maximum=240)
)
else:
target = translate_message("the current local workspace", language=language)
effect = "read" if is_read_only else ("local_execution" if read_only_known else "unknown")
elif tool_name in {"write_file", "edit_file"}:
title = translate_message("Change a workspace file", language=language)
purpose = translate_message(
"Write a file needed for the requested infrastructure task.", language=language
)
purpose = translate_message("Write a file needed for the requested infrastructure task.", language=language)
target = _safe_input_target(safe_input, language=language) or translate_message(
"a file in the current workspace", language=language
)
effect = "file_change"
elif tool_name in {"read_file", "glob", "grep"} or is_read_only:
title = translate_message("Read workspace data with {tool}", language=language).format(tool=public_tool)
purpose = translate_message(
"Read local data needed for the requested infrastructure task.", language=language
)
purpose = translate_message("Read local data needed for the requested infrastructure task.", language=language)
target = _safe_input_target(safe_input, language=language) or translate_message(
"the current local workspace", language=language
)
effect = "read"
else:
title = translate_message("Run {tool}", language=language).format(tool=public_tool)
purpose = translate_message(
"Run this operation for the requested infrastructure task.", language=language
)
purpose = translate_message("Run this operation for the requested infrastructure task.", language=language)
target = _safe_input_target(safe_input, language=language) or translate_message(
"the current task workspace or cloud account", language=language
)
Expand Down Expand Up @@ -319,9 +313,7 @@ def _cloud_operation_title(product: str, action: str, *, is_read_only: bool, lan
if action == "CreateStack":
return translate_message("Create {product} stack", language=language).format(product=product_label)
if action == "ContinueCreateStack":
return translate_message("Continue creating {product} stack", language=language).format(
product=product_label
)
return translate_message("Continue creating {product} stack", language=language).format(product=product_label)
if action == "UpdateStack":
return translate_message("Update {product} stack", language=language).format(product=product_label)
if action == "DeleteStack":
Expand All @@ -344,9 +336,7 @@ def _safe_input_target(value: Any, *, language: str) -> str:
for key in ("file_path", "filePath", "path", "region_id", "regionId", "resource_id", "resourceId"):
candidate = value.get(key)
if isinstance(candidate, str) and candidate.strip():
return _display_text(
candidate, fallback=translate_message("the current task scope", language=language)
)
return _display_text(candidate, fallback=translate_message("the current task scope", language=language))
return ""


Expand Down
16 changes: 16 additions & 0 deletions src/iac_code/a2a/pipeline_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,8 @@ def _translate_sub_pipeline_stream_event(self, event: SubPipelineStreamEvent) ->
cost_items=inner.cost_items,
total_monthly_cost=inner.total_monthly_cost,
candidate_index=inner.candidate_index,
planning_monthly_estimate=inner.planning_monthly_estimate,
cost_caliber_note=inner.cost_caliber_note,
)
self._mark_candidate_detail_emitted(inner.tool_use_id)
input_data = None
Expand Down Expand Up @@ -701,6 +703,8 @@ def _translate_candidate_detail_event(self, event: CandidateDetailEvent) -> dict
cost_items=event.cost_items,
total_monthly_cost=event.total_monthly_cost,
candidate_index=event.candidate_index,
planning_monthly_estimate=event.planning_monthly_estimate,
cost_caliber_note=event.cost_caliber_note,
)
self._mark_candidate_detail_emitted(event.tool_use_id)
return self._translate_parent_scoped_display_event("candidate_detail_shown", data)
Expand Down Expand Up @@ -1613,13 +1617,19 @@ def _candidate_detail_data(
cost_items: list[dict],
total_monthly_cost: str,
candidate_index: int | None = None,
planning_monthly_estimate: str = "",
cost_caliber_note: str = "",
) -> dict[str, Any]:
detail: dict[str, Any] = {
"candidateName": candidate_name,
"summary": summary,
"costItems": cost_items,
"totalMonthlyCost": total_monthly_cost,
}
if planning_monthly_estimate:
detail["planningMonthlyEstimate"] = planning_monthly_estimate
if cost_caliber_note:
detail["costCaliberNote"] = cost_caliber_note
data: dict[str, Any] = {
"detailId": f"detail-{tool_use_id}",
"toolUseId": tool_use_id,
Expand All @@ -1635,6 +1645,10 @@ def _candidate_detail_data_from_tool_input(tool_use_id: str, tool_input: dict[st
candidate_name = _first_string_value(tool_input, ("candidate_name", "candidateName"))
summary = _first_string_value(tool_input, ("summary",))
total_monthly_cost = _first_string_value(tool_input, ("total_monthly_cost", "totalMonthlyCost"))
planning_monthly_estimate = _first_string_value(
tool_input, ("planning_monthly_estimate", "planningMonthlyEstimate")
)
cost_caliber_note = _first_string_value(tool_input, ("cost_caliber_note", "costCaliberNote"))
candidate_index = _int_or_none(tool_input.get("candidate_index"))
if candidate_index is None:
candidate_index = _int_or_none(tool_input.get("candidateIndex"))
Expand All @@ -1650,6 +1664,8 @@ def _candidate_detail_data_from_tool_input(tool_use_id: str, tool_input: dict[st
cost_items=[item for item in cost_items if isinstance(item, dict)],
total_monthly_cost=total_monthly_cost,
candidate_index=candidate_index,
planning_monthly_estimate=planning_monthly_estimate or "",
cost_caliber_note=cost_caliber_note or "",
)


Expand Down
6 changes: 1 addition & 5 deletions src/iac_code/a2a/pipeline_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1235,11 +1235,7 @@ def _create_pipeline(
def permission_context_getter() -> Any:
return getattr(agent_loop, "_permission_context", None)

surface = (
A2A_RICH_CANDIDATE_SURFACE
if self._candidate_presentation == RICH_CANDIDATE_PRESENTATION
else "a2a"
)
surface = A2A_RICH_CANDIDATE_SURFACE if self._candidate_presentation == RICH_CANDIDATE_PRESENTATION else "a2a"
return create_pipeline(
pipeline_name,
provider_manager=runtime.provider_manager,
Expand Down
6 changes: 6 additions & 0 deletions src/iac_code/a2a/pipeline_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,12 @@ def _unified_input_projection(
projected_option["architectureDiagram"] = architecture_diagram[:1600]
if isinstance(total_monthly_cost, str) and total_monthly_cost:
projected_option["totalMonthlyCost"] = total_monthly_cost[:300]
planning_estimate = option.get("planning_monthly_estimate") or option.get("planningMonthlyEstimate")
if isinstance(planning_estimate, str) and planning_estimate:
projected_option["planningMonthlyEstimate"] = planning_estimate[:300]
caliber_note = option.get("cost_caliber_note") or option.get("costCaliberNote")
if isinstance(caliber_note, str) and caliber_note:
projected_option["costCaliberNote"] = caliber_note[:600]
raw_cost_items = option.get("cost_items") or option.get("costItems")
cost_items: list[dict[str, str]] = []
if isinstance(raw_cost_items, list):
Expand Down
4 changes: 1 addition & 3 deletions src/iac_code/a2a/task_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -864,9 +864,7 @@ async def has_active_work(self) -> bool:
any(record.active_task is not None and not record.active_task.done() for record in self._tasks.values())
or any(not task.done() for task in self._context_runtime_tasks.values())
or any(
not task.done()
for starts in self._context_execution_starts.values()
for task in starts.values()
not task.done() for starts in self._context_execution_starts.values() for task in starts.values()
)
or any(self._context_reconciliation_waiters.values())
or any(lock.locked() for lock in self._reconciliation_locks.values())
Expand Down
34 changes: 34 additions & 0 deletions src/iac_code/i18n/locales/de/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -4086,6 +4086,16 @@ msgstr ""
"eine erfolgreiche Prüfung mit übereinstimmenden Parametern und Nachweisen"
" abgedeckt sein."

#: src/iac_code/pipeline/engine/complete_step_tool.py
msgid ""
"The pricing conclusion must reconcile the planning estimate with the ROS "
"list price and give a contract discount source for any discounted "
"effective price."
msgstr ""
"Das Kostenergebnis muss die Planungsschätzung mit dem ROS-Listenpreis "
"abgleichen und für jeden rabattierten Effektivpreis die Quelle des "
"Vertragsrabatts angeben."

#: src/iac_code/pipeline/engine/complete_step_tool.py
msgid ""
"Complete the current step by calling this tool to submit the conclusion. "
Expand Down Expand Up @@ -4866,6 +4876,18 @@ msgstr "Liste der Kostenaufschlüsselung"
msgid "Total monthly cost, such as CNY 1,234/month"
msgstr "Gesamte monatliche Kosten, z. B. CNY 1.234/Monat"

#: src/iac_code/pipeline/selling/tools/show_candidate_detail_tool.py
msgid "Rough monthly estimate from architecture planning, at list-price caliber"
msgstr ""
"Grobe monatliche Schätzung aus der Architekturplanung, nach Listenpreis-"
"Maßstab"

#: src/iac_code/pipeline/selling/tools/show_candidate_detail_tool.py
msgid ""
"Explanation of the deviation between the planning estimate and the final "
"cost"
msgstr "Erläuterung der Abweichung zwischen Planungsschätzung und Endkosten"

#: src/iac_code/pipeline/selling/tools/show_candidate_detail_tool.py
#, python-brace-format
msgid "Displayed details for \"{candidate_name}\"."
Expand Down Expand Up @@ -9959,6 +9981,18 @@ msgstr " ✓ Ausgewählt: {name}"
msgid " Candidate selection completed"
msgstr " Kandidatenauswahl abgeschlossen"

#: src/iac_code/ui/components/candidate_selection.py
#: src/iac_code/ui/pipeline_display_replay.py
#, python-brace-format
msgid "Planning estimate: {estimate}"
msgstr "Planungsschätzung: {estimate}"

#: src/iac_code/ui/components/candidate_selection.py
#: src/iac_code/ui/pipeline_display_replay.py
#, python-brace-format
msgid "Cost caliber: {note}"
msgstr "Kostenmaßstab: {note}"

#: src/iac_code/ui/components/candidate_selection.py
#: src/iac_code/ui/pipeline_display_replay.py
msgid "Cost details"
Expand Down
24 changes: 16 additions & 8 deletions src/iac_code/i18n/locales/de/LC_MESSAGES/webui.po
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,14 @@ msgstr "{n}Wo"
msgid "{n}y"
msgstr "{n}J"

#: src/iac_code/web/static/js/app.js
msgid "Operation failed"
msgstr "Vorgang fehlgeschlagen"

#: src/iac_code/web/static/js/app.js
msgid "Archive failed"
msgstr "Archivierung fehlgeschlagen"

#: src/iac_code/web/static/js/app.js
msgid "Read-only"
msgstr "Schreibgeschützt"
Expand All @@ -561,14 +569,6 @@ msgstr "Bitte geben Sie einen Inhalt ein"
msgid "Please enter a name"
msgstr "Bitte geben Sie einen Namen ein"

#: src/iac_code/web/static/js/app.js
msgid "Operation failed"
msgstr "Vorgang fehlgeschlagen"

#: src/iac_code/web/static/js/app.js
msgid "Archive failed"
msgstr "Archivierung fehlgeschlagen"

#: src/iac_code/web/static/js/app.js
#, python-brace-format
msgid "Remove {label}?"
Expand Down Expand Up @@ -953,6 +953,14 @@ msgstr "Keine Preisinformationen"
msgid "Estimated monthly cost"
msgstr "Geschätzte monatliche Kosten"

#: src/iac_code/web/static/js/mermaid_render.js
msgid "Planning estimate"
msgstr "Planungsschätzung"

#: src/iac_code/web/static/js/mermaid_render.js
msgid "Cost caliber"
msgstr "Kostenmaßstab"

#: src/iac_code/web/static/js/token_transport.js
msgid "Enter Web access token"
msgstr "Web-Zugriffstoken eingeben"
Expand Down
36 changes: 36 additions & 0 deletions src/iac_code/i18n/locales/es/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -4063,6 +4063,16 @@ msgstr ""
"Cada restricción estricta explícita del usuario debe estar cubierta por "
"una comprobación satisfactoria con parámetros y evidencias coincidentes."

#: src/iac_code/pipeline/engine/complete_step_tool.py
msgid ""
"The pricing conclusion must reconcile the planning estimate with the ROS "
"list price and give a contract discount source for any discounted "
"effective price."
msgstr ""
"La conclusión de costos debe conciliar la estimación de planificación con"
" el precio de lista de ROS e indicar la fuente del descuento contractual "
"de cualquier precio efectivo con descuento."

#: src/iac_code/pipeline/engine/complete_step_tool.py
msgid ""
"Complete the current step by calling this tool to submit the conclusion. "
Expand Down Expand Up @@ -4832,6 +4842,20 @@ msgstr "Lista de desglose de costos"
msgid "Total monthly cost, such as CNY 1,234/month"
msgstr "Costo mensual total, por ejemplo CNY 1.234/mes"

#: src/iac_code/pipeline/selling/tools/show_candidate_detail_tool.py
msgid "Rough monthly estimate from architecture planning, at list-price caliber"
msgstr ""
"Estimación mensual aproximada de la planificación de arquitectura, con "
"criterio de precio de lista"

#: src/iac_code/pipeline/selling/tools/show_candidate_detail_tool.py
msgid ""
"Explanation of the deviation between the planning estimate and the final "
"cost"
msgstr ""
"Explicación de la desviación entre la estimación de planificación y el "
"costo final"

#: src/iac_code/pipeline/selling/tools/show_candidate_detail_tool.py
#, python-brace-format
msgid "Displayed details for \"{candidate_name}\"."
Expand Down Expand Up @@ -9891,6 +9915,18 @@ msgstr " ✓ Seleccionado: {name}"
msgid " Candidate selection completed"
msgstr " Selección de candidato completada"

#: src/iac_code/ui/components/candidate_selection.py
#: src/iac_code/ui/pipeline_display_replay.py
#, python-brace-format
msgid "Planning estimate: {estimate}"
msgstr "Estimación de planificación: {estimate}"

#: src/iac_code/ui/components/candidate_selection.py
#: src/iac_code/ui/pipeline_display_replay.py
#, python-brace-format
msgid "Cost caliber: {note}"
msgstr "Criterio de costo: {note}"

#: src/iac_code/ui/components/candidate_selection.py
#: src/iac_code/ui/pipeline_display_replay.py
msgid "Cost details"
Expand Down
24 changes: 16 additions & 8 deletions src/iac_code/i18n/locales/es/LC_MESSAGES/webui.po
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,14 @@ msgstr "{n}sem"
msgid "{n}y"
msgstr "{n}a"

#: src/iac_code/web/static/js/app.js
msgid "Operation failed"
msgstr "La operación falló"

#: src/iac_code/web/static/js/app.js
msgid "Archive failed"
msgstr "Error al archivar"

#: src/iac_code/web/static/js/app.js
msgid "Read-only"
msgstr "Solo lectura"
Expand All @@ -563,14 +571,6 @@ msgstr "Introduce contenido"
msgid "Please enter a name"
msgstr "Introduce un nombre"

#: src/iac_code/web/static/js/app.js
msgid "Operation failed"
msgstr "La operación falló"

#: src/iac_code/web/static/js/app.js
msgid "Archive failed"
msgstr "Error al archivar"

#: src/iac_code/web/static/js/app.js
#, python-brace-format
msgid "Remove {label}?"
Expand Down Expand Up @@ -952,6 +952,14 @@ msgstr "Sin información de precios"
msgid "Estimated monthly cost"
msgstr "Costo mensual estimado"

#: src/iac_code/web/static/js/mermaid_render.js
msgid "Planning estimate"
msgstr "Estimación de planificación"

#: src/iac_code/web/static/js/mermaid_render.js
msgid "Cost caliber"
msgstr "Criterio de costo"

#: src/iac_code/web/static/js/token_transport.js
msgid "Enter Web access token"
msgstr "Introduzca el token de acceso web"
Expand Down
Loading
Loading