flowent 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/pyproject.toml +1 -1
- package/backend/src/flowent/agent.py +1 -0
- package/backend/src/flowent/approval.py +6 -4
- package/backend/src/flowent/context.py +2 -0
- package/backend/src/flowent/llm.py +9 -4
- package/backend/src/flowent/main.py +447 -81
- package/backend/src/flowent/permissions.py +5 -2
- package/backend/src/flowent/shell.py +94 -0
- package/backend/src/flowent/static/assets/index-D7t9qNrC.js +82 -0
- package/backend/src/flowent/static/assets/index-DufpDl8x.css +2 -0
- package/backend/src/flowent/static/index.html +2 -2
- package/backend/src/flowent/storage.py +16 -4
- package/backend/src/flowent/tools.py +5 -2
- package/backend/uv.lock +1 -1
- package/dist/frontend/assets/index-D7t9qNrC.js +82 -0
- package/dist/frontend/assets/index-DufpDl8x.css +2 -0
- package/dist/frontend/index.html +2 -2
- package/package.json +1 -1
- package/backend/src/flowent/static/assets/index-CRSV2xu1.css +0 -2
- package/backend/src/flowent/static/assets/index-DUYj6rgD.js +0 -82
- package/dist/frontend/assets/index-CRSV2xu1.css +0 -2
- package/dist/frontend/assets/index-DUYj6rgD.js +0 -82
package/backend/pyproject.toml
CHANGED
|
@@ -240,6 +240,7 @@ async def run_agent_stream(
|
|
|
240
240
|
round_number,
|
|
241
241
|
tool_calls,
|
|
242
242
|
)
|
|
243
|
+
yield AgentStreamEvent(event="output_done", data={"index": round_number})
|
|
243
244
|
if not tool_calls:
|
|
244
245
|
if not final_content and not final_thinking:
|
|
245
246
|
raise RuntimeError(EMPTY_MODEL_RESPONSE_ERROR)
|
|
@@ -12,7 +12,7 @@ from flowent.llm import (
|
|
|
12
12
|
ChatMessage,
|
|
13
13
|
CompletionCallable,
|
|
14
14
|
ProviderConnection,
|
|
15
|
-
|
|
15
|
+
stream_chat,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
logger = logging.getLogger("flowent.approval")
|
|
@@ -128,7 +128,8 @@ async def review_approval_request(
|
|
|
128
128
|
completion: CompletionCallable | None = None,
|
|
129
129
|
) -> ApprovalReviewDecision:
|
|
130
130
|
try:
|
|
131
|
-
|
|
131
|
+
content = ""
|
|
132
|
+
async for delta in stream_chat(
|
|
132
133
|
connection,
|
|
133
134
|
[
|
|
134
135
|
ChatMessage(role="system", content=APPROVAL_REVIEWER_PROMPT),
|
|
@@ -138,8 +139,9 @@ async def review_approval_request(
|
|
|
138
139
|
),
|
|
139
140
|
],
|
|
140
141
|
completion=completion,
|
|
141
|
-
)
|
|
142
|
-
|
|
142
|
+
):
|
|
143
|
+
content += delta
|
|
144
|
+
return parse_review_decision(content)
|
|
143
145
|
except Exception as error:
|
|
144
146
|
logger.warning("Approval reviewer denied request after failure: %s", error)
|
|
145
147
|
return ApprovalReviewDecision(
|
|
@@ -4,6 +4,7 @@ import os
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
6
|
from flowent.llm import ChatMessage
|
|
7
|
+
from flowent.shell import shell_invocation_description
|
|
7
8
|
from flowent.tools import tool_specs
|
|
8
9
|
|
|
9
10
|
DEFAULT_PROJECT_INSTRUCTIONS_MAX_BYTES = 32768
|
|
@@ -108,6 +109,7 @@ def environment_context_message(cwd: Path) -> ChatMessage:
|
|
|
108
109
|
content=(
|
|
109
110
|
"<environment_context>\n"
|
|
110
111
|
f" <cwd>{cwd.resolve(strict=False)}</cwd>\n"
|
|
112
|
+
f" <shell>{shell_invocation_description()}</shell>\n"
|
|
111
113
|
" <filesystem>workspace-write</filesystem>\n"
|
|
112
114
|
" <network>enabled</network>\n"
|
|
113
115
|
" <tools>\n"
|
|
@@ -108,6 +108,7 @@ MODEL_PREFIXES: dict[ProviderFormat, str] = {
|
|
|
108
108
|
ProviderFormat.ANTHROPIC: "anthropic",
|
|
109
109
|
ProviderFormat.GEMINI: "gemini",
|
|
110
110
|
}
|
|
111
|
+
OPENAI_RESPONSES_MODEL_PREFIX = "responses/"
|
|
111
112
|
_litellm_stream_error_patch_installed = False
|
|
112
113
|
|
|
113
114
|
PROVIDER_API_VERSIONS: dict[ProviderFormat, str] = {
|
|
@@ -121,7 +122,10 @@ VERSION_PATH_SEGMENT = re.compile(r"^v\d+(?:[a-z]+)?$", re.IGNORECASE)
|
|
|
121
122
|
|
|
122
123
|
|
|
123
124
|
def provider_model_name(connection: ProviderConnection) -> str:
|
|
124
|
-
|
|
125
|
+
model = normalize_provider_model_name(connection.provider, connection.model)
|
|
126
|
+
if connection.provider == ProviderFormat.OPENAI_RESPONSES:
|
|
127
|
+
model = f"{OPENAI_RESPONSES_MODEL_PREFIX}{model}"
|
|
128
|
+
return f"{MODEL_PREFIXES[connection.provider]}/{model}"
|
|
125
129
|
|
|
126
130
|
|
|
127
131
|
def provider_litellm_name(provider: ProviderFormat) -> str:
|
|
@@ -164,9 +168,10 @@ def normalize_provider_base_url(
|
|
|
164
168
|
|
|
165
169
|
def normalize_provider_model_name(provider: ProviderFormat, model: str) -> str:
|
|
166
170
|
prefix = f"{provider_litellm_name(provider)}/"
|
|
167
|
-
if model.startswith(prefix)
|
|
168
|
-
|
|
169
|
-
|
|
171
|
+
normalized_model = model.removeprefix(prefix) if model.startswith(prefix) else model
|
|
172
|
+
if provider == ProviderFormat.OPENAI_RESPONSES:
|
|
173
|
+
return normalized_model.removeprefix(OPENAI_RESPONSES_MODEL_PREFIX)
|
|
174
|
+
return normalized_model
|
|
170
175
|
|
|
171
176
|
|
|
172
177
|
def stream_failure_message(chunk: Any) -> str:
|