CI / test (push) Canceled after 0s
## Summary epic r04 - begin refactor ## Change Type - [x] Cowork feature - [ ] Bug fix - [ ] Core AI contribution - [ ] Test / hardening - [ ] Performance - [ ] Documentation ## Related Work Cowork Task: Core Repo: http://34.143.229.138/gitea-admin/fsg-ai-core-assets Core AI Issue: Core Task: Related PR: ## Scope What is intentionally included? What is intentionally NOT included? ## Validation - [ ] Unit tests - [ ] Integration tests - [ ] Manual verification - [ ] Regression check Commands / evidence: ## Security Impact Permission / credential / network / customer data impact: ## Compatibility - [ ] No breaking change - [ ] Breaking change documented ## Reviewer Notes Anything Cowork reviewers should pay attention to. --------- Co-authored-by: Anh Tran Nguyen Minh <anhtnm1@fpt.com> Co-authored-by: Huong Le Thi Thien <huongltt35@fpt.com> Co-authored-by: Nam Pham Dinh Thanh <nampdt@fpt.com> Co-authored-by: Vu Dam Tuan <vudt15@fpt.com> Co-authored-by: Hiep Ha Van <hiephv3@fpt.com> Co-authored-by: Lam Hoang Van <lamhv7@fpt.com> Reviewed-on: #7 Co-authored-by: Duy Le Huu <duylh19@fpt.com>
78 lines
3.0 KiB
Python
78 lines
3.0 KiB
Python
"""Turn the Cowork widget's captured state into a request (R04-T04).
|
|
|
|
``ui/cowork_tab.py::build_job`` reads a dozen values off the widget on the UI
|
|
thread and has to translate three of them before a turn can run: which message
|
|
is this turn's prompt, which messages are its history, and whether the workspace
|
|
wants commands confirmed. Those rules lived inline in the widget, where no test
|
|
could reach them — and each fails silently when wrong (a duplicated user message,
|
|
or a command that quietly stops asking for approval).
|
|
|
|
They live here instead, as the mapping step the migration map assigns to the
|
|
application layer. The widget keeps only what is genuinely widget-specific:
|
|
reading its own state and building the provider.
|
|
|
|
Layer rules (``docs/architecture/ADR-001-layered-architecture.md``): pure Python.
|
|
Everything arrives as a plain value, so this module never sees a widget.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Dict, Optional, Sequence
|
|
|
|
from ...domain.agents.conversation_execution_request import ConversationExecutionRequest
|
|
|
|
|
|
def build_cowork_turn_request(
|
|
*,
|
|
turn_id: str,
|
|
session_id: str,
|
|
messages: Sequence[Dict[str, Any]],
|
|
surface: str = "cowork",
|
|
project_id: str = "",
|
|
title: str = "",
|
|
provider_id: str = "",
|
|
model: str = "",
|
|
instructions: str = "",
|
|
output_dir: Optional[Any] = None,
|
|
home_output_root: Optional[Any] = None,
|
|
confirm_commands: bool = False,
|
|
agent_role: str = "cowork",
|
|
) -> ConversationExecutionRequest:
|
|
"""Build one Cowork turn's immutable request.
|
|
|
|
``messages`` is the widget's working list, which ALREADY ends with this
|
|
turn's user message (the chat panel composes it — prefix, attachments,
|
|
session notes — before the job starts). So the prompt is that last message
|
|
and the history is everything before it. The request records both; the
|
|
service is handed the same working list and appends into it.
|
|
|
|
Keyword-only on purpose: a dozen positional strings in a call site is exactly
|
|
how a title ends up in the project-id slot.
|
|
"""
|
|
history = list(messages or ())
|
|
# ``pop`` rather than ``[-1]``/``[:-1]`` so the empty-list case needs no
|
|
# special branch: a turn with nothing in it yields an empty prompt instead of
|
|
# raising IndexError deep inside a worker thread.
|
|
last = history.pop() if history else {}
|
|
return ConversationExecutionRequest(
|
|
turn_id=turn_id,
|
|
session_id=session_id,
|
|
surface=surface,
|
|
project_id=project_id,
|
|
title=title,
|
|
prompt=str(last.get("content") or ""),
|
|
messages=history,
|
|
provider_id=provider_id,
|
|
model=model,
|
|
project_context=instructions,
|
|
output_dir=output_dir,
|
|
home_output_root=home_output_root,
|
|
# The workspace's Auto-run override (or the global setting) decides
|
|
# whether run_command/install_package must be approved first.
|
|
gate_mode="confirm" if confirm_commands else "auto",
|
|
agent_role=agent_role,
|
|
)
|
|
|
|
|
|
__all__ = ["build_cowork_turn_request"]
|