superqode 0.1.5__py3-none-any.whl
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.
- superqode/__init__.py +33 -0
- superqode/acp/__init__.py +23 -0
- superqode/acp/client.py +913 -0
- superqode/acp/permission_screen.py +457 -0
- superqode/acp/types.py +480 -0
- superqode/acp_discovery.py +856 -0
- superqode/agent/__init__.py +22 -0
- superqode/agent/edit_strategies.py +334 -0
- superqode/agent/loop.py +892 -0
- superqode/agent/qe_report_templates.py +39 -0
- superqode/agent/system_prompts.py +353 -0
- superqode/agent_output.py +721 -0
- superqode/agent_stream.py +953 -0
- superqode/agents/__init__.py +59 -0
- superqode/agents/acp_registry.py +305 -0
- superqode/agents/client.py +249 -0
- superqode/agents/data/augmentcode.com.toml +51 -0
- superqode/agents/data/cagent.dev.toml +51 -0
- superqode/agents/data/claude.com.toml +60 -0
- superqode/agents/data/codeassistant.dev.toml +51 -0
- superqode/agents/data/codex.openai.com.toml +57 -0
- superqode/agents/data/fastagent.ai.toml +66 -0
- superqode/agents/data/geminicli.com.toml +77 -0
- superqode/agents/data/goose.block.xyz.toml +54 -0
- superqode/agents/data/junie.jetbrains.com.toml +56 -0
- superqode/agents/data/kimi.moonshot.cn.toml +57 -0
- superqode/agents/data/llmlingagent.dev.toml +51 -0
- superqode/agents/data/molt.bot.toml +49 -0
- superqode/agents/data/opencode.ai.toml +60 -0
- superqode/agents/data/stakpak.dev.toml +51 -0
- superqode/agents/data/vtcode.dev.toml +51 -0
- superqode/agents/discovery.py +266 -0
- superqode/agents/messaging.py +160 -0
- superqode/agents/persona.py +166 -0
- superqode/agents/registry.py +421 -0
- superqode/agents/schema.py +72 -0
- superqode/agents/unified.py +367 -0
- superqode/app/__init__.py +111 -0
- superqode/app/constants.py +314 -0
- superqode/app/css.py +366 -0
- superqode/app/models.py +118 -0
- superqode/app/suggester.py +125 -0
- superqode/app/widgets.py +1591 -0
- superqode/app_enhanced.py +399 -0
- superqode/app_main.py +17187 -0
- superqode/approval.py +312 -0
- superqode/atomic.py +296 -0
- superqode/commands/__init__.py +1 -0
- superqode/commands/acp.py +965 -0
- superqode/commands/agents.py +180 -0
- superqode/commands/auth.py +278 -0
- superqode/commands/config.py +374 -0
- superqode/commands/init.py +826 -0
- superqode/commands/providers.py +819 -0
- superqode/commands/qe.py +1145 -0
- superqode/commands/roles.py +380 -0
- superqode/commands/serve.py +172 -0
- superqode/commands/suggestions.py +127 -0
- superqode/commands/superqe.py +460 -0
- superqode/config/__init__.py +51 -0
- superqode/config/loader.py +812 -0
- superqode/config/schema.py +498 -0
- superqode/core/__init__.py +111 -0
- superqode/core/roles.py +281 -0
- superqode/danger.py +386 -0
- superqode/data/superqode-template.yaml +1522 -0
- superqode/design_system.py +1080 -0
- superqode/dialogs/__init__.py +6 -0
- superqode/dialogs/base.py +39 -0
- superqode/dialogs/model.py +130 -0
- superqode/dialogs/provider.py +870 -0
- superqode/diff_view.py +919 -0
- superqode/enterprise.py +21 -0
- superqode/evaluation/__init__.py +25 -0
- superqode/evaluation/adapters.py +93 -0
- superqode/evaluation/behaviors.py +89 -0
- superqode/evaluation/engine.py +209 -0
- superqode/evaluation/scenarios.py +96 -0
- superqode/execution/__init__.py +36 -0
- superqode/execution/linter.py +538 -0
- superqode/execution/modes.py +347 -0
- superqode/execution/resolver.py +283 -0
- superqode/execution/runner.py +642 -0
- superqode/file_explorer.py +811 -0
- superqode/file_viewer.py +471 -0
- superqode/flash.py +183 -0
- superqode/guidance/__init__.py +58 -0
- superqode/guidance/config.py +203 -0
- superqode/guidance/prompts.py +71 -0
- superqode/harness/__init__.py +54 -0
- superqode/harness/accelerator.py +291 -0
- superqode/harness/config.py +319 -0
- superqode/harness/validator.py +147 -0
- superqode/history.py +279 -0
- superqode/integrations/superopt_runner.py +124 -0
- superqode/logging/__init__.py +49 -0
- superqode/logging/adapters.py +219 -0
- superqode/logging/formatter.py +923 -0
- superqode/logging/integration.py +341 -0
- superqode/logging/sinks.py +170 -0
- superqode/logging/unified_log.py +417 -0
- superqode/lsp/__init__.py +26 -0
- superqode/lsp/client.py +544 -0
- superqode/main.py +1069 -0
- superqode/mcp/__init__.py +89 -0
- superqode/mcp/auth_storage.py +380 -0
- superqode/mcp/client.py +1236 -0
- superqode/mcp/config.py +319 -0
- superqode/mcp/integration.py +337 -0
- superqode/mcp/oauth.py +436 -0
- superqode/mcp/oauth_callback.py +385 -0
- superqode/mcp/types.py +290 -0
- superqode/memory/__init__.py +31 -0
- superqode/memory/feedback.py +342 -0
- superqode/memory/store.py +522 -0
- superqode/notifications.py +369 -0
- superqode/optimization/__init__.py +5 -0
- superqode/optimization/config.py +33 -0
- superqode/permissions/__init__.py +25 -0
- superqode/permissions/rules.py +488 -0
- superqode/plan.py +323 -0
- superqode/providers/__init__.py +33 -0
- superqode/providers/gateway/__init__.py +165 -0
- superqode/providers/gateway/base.py +228 -0
- superqode/providers/gateway/litellm_gateway.py +1170 -0
- superqode/providers/gateway/openresponses_gateway.py +436 -0
- superqode/providers/health.py +297 -0
- superqode/providers/huggingface/__init__.py +74 -0
- superqode/providers/huggingface/downloader.py +472 -0
- superqode/providers/huggingface/endpoints.py +442 -0
- superqode/providers/huggingface/hub.py +531 -0
- superqode/providers/huggingface/inference.py +394 -0
- superqode/providers/huggingface/transformers_runner.py +516 -0
- superqode/providers/local/__init__.py +100 -0
- superqode/providers/local/base.py +438 -0
- superqode/providers/local/discovery.py +418 -0
- superqode/providers/local/lmstudio.py +256 -0
- superqode/providers/local/mlx.py +457 -0
- superqode/providers/local/ollama.py +486 -0
- superqode/providers/local/sglang.py +268 -0
- superqode/providers/local/tgi.py +260 -0
- superqode/providers/local/tool_support.py +477 -0
- superqode/providers/local/vllm.py +258 -0
- superqode/providers/manager.py +1338 -0
- superqode/providers/models.py +1016 -0
- superqode/providers/models_dev.py +578 -0
- superqode/providers/openresponses/__init__.py +87 -0
- superqode/providers/openresponses/converters/__init__.py +17 -0
- superqode/providers/openresponses/converters/messages.py +343 -0
- superqode/providers/openresponses/converters/tools.py +268 -0
- superqode/providers/openresponses/schema/__init__.py +56 -0
- superqode/providers/openresponses/schema/models.py +585 -0
- superqode/providers/openresponses/streaming/__init__.py +5 -0
- superqode/providers/openresponses/streaming/parser.py +338 -0
- superqode/providers/openresponses/tools/__init__.py +21 -0
- superqode/providers/openresponses/tools/apply_patch.py +352 -0
- superqode/providers/openresponses/tools/code_interpreter.py +290 -0
- superqode/providers/openresponses/tools/file_search.py +333 -0
- superqode/providers/openresponses/tools/mcp_adapter.py +252 -0
- superqode/providers/registry.py +716 -0
- superqode/providers/usage.py +332 -0
- superqode/pure_mode.py +384 -0
- superqode/qr/__init__.py +23 -0
- superqode/qr/dashboard.py +781 -0
- superqode/qr/generator.py +1018 -0
- superqode/qr/templates.py +135 -0
- superqode/safety/__init__.py +41 -0
- superqode/safety/sandbox.py +413 -0
- superqode/safety/warnings.py +256 -0
- superqode/server/__init__.py +33 -0
- superqode/server/lsp_server.py +775 -0
- superqode/server/web.py +250 -0
- superqode/session/__init__.py +25 -0
- superqode/session/persistence.py +580 -0
- superqode/session/sharing.py +477 -0
- superqode/session.py +475 -0
- superqode/sidebar.py +2991 -0
- superqode/stream_view.py +648 -0
- superqode/styles/__init__.py +3 -0
- superqode/superqe/__init__.py +184 -0
- superqode/superqe/acp_runner.py +1064 -0
- superqode/superqe/constitution/__init__.py +62 -0
- superqode/superqe/constitution/evaluator.py +308 -0
- superqode/superqe/constitution/loader.py +432 -0
- superqode/superqe/constitution/schema.py +250 -0
- superqode/superqe/events.py +591 -0
- superqode/superqe/frameworks/__init__.py +65 -0
- superqode/superqe/frameworks/base.py +234 -0
- superqode/superqe/frameworks/e2e.py +263 -0
- superqode/superqe/frameworks/executor.py +237 -0
- superqode/superqe/frameworks/javascript.py +409 -0
- superqode/superqe/frameworks/python.py +373 -0
- superqode/superqe/frameworks/registry.py +92 -0
- superqode/superqe/mcp_tools/__init__.py +47 -0
- superqode/superqe/mcp_tools/core_tools.py +418 -0
- superqode/superqe/mcp_tools/registry.py +230 -0
- superqode/superqe/mcp_tools/testing_tools.py +167 -0
- superqode/superqe/noise.py +89 -0
- superqode/superqe/orchestrator.py +778 -0
- superqode/superqe/roles.py +609 -0
- superqode/superqe/session.py +713 -0
- superqode/superqe/skills/__init__.py +57 -0
- superqode/superqe/skills/base.py +106 -0
- superqode/superqe/skills/core_skills.py +899 -0
- superqode/superqe/skills/registry.py +90 -0
- superqode/superqe/verifier.py +101 -0
- superqode/superqe_cli.py +76 -0
- superqode/tool_call.py +358 -0
- superqode/tools/__init__.py +93 -0
- superqode/tools/agent_tools.py +496 -0
- superqode/tools/base.py +324 -0
- superqode/tools/batch_tool.py +133 -0
- superqode/tools/diagnostics.py +311 -0
- superqode/tools/edit_tools.py +653 -0
- superqode/tools/enhanced_base.py +515 -0
- superqode/tools/file_tools.py +269 -0
- superqode/tools/file_tracking.py +45 -0
- superqode/tools/lsp_tools.py +610 -0
- superqode/tools/network_tools.py +350 -0
- superqode/tools/permissions.py +400 -0
- superqode/tools/question_tool.py +324 -0
- superqode/tools/search_tools.py +598 -0
- superqode/tools/shell_tools.py +259 -0
- superqode/tools/todo_tools.py +121 -0
- superqode/tools/validation.py +80 -0
- superqode/tools/web_tools.py +639 -0
- superqode/tui.py +1152 -0
- superqode/tui_integration.py +875 -0
- superqode/tui_widgets/__init__.py +27 -0
- superqode/tui_widgets/widgets/__init__.py +18 -0
- superqode/tui_widgets/widgets/progress.py +185 -0
- superqode/tui_widgets/widgets/tool_display.py +188 -0
- superqode/undo_manager.py +574 -0
- superqode/utils/__init__.py +5 -0
- superqode/utils/error_handling.py +323 -0
- superqode/utils/fuzzy.py +257 -0
- superqode/widgets/__init__.py +477 -0
- superqode/widgets/agent_collab.py +390 -0
- superqode/widgets/agent_store.py +936 -0
- superqode/widgets/agent_switcher.py +395 -0
- superqode/widgets/animation_manager.py +284 -0
- superqode/widgets/code_context.py +356 -0
- superqode/widgets/command_palette.py +412 -0
- superqode/widgets/connection_status.py +537 -0
- superqode/widgets/conversation_history.py +470 -0
- superqode/widgets/diff_indicator.py +155 -0
- superqode/widgets/enhanced_status_bar.py +385 -0
- superqode/widgets/enhanced_toast.py +476 -0
- superqode/widgets/file_browser.py +809 -0
- superqode/widgets/file_reference.py +585 -0
- superqode/widgets/issue_timeline.py +340 -0
- superqode/widgets/leader_key.py +264 -0
- superqode/widgets/mode_switcher.py +445 -0
- superqode/widgets/model_picker.py +234 -0
- superqode/widgets/permission_preview.py +1205 -0
- superqode/widgets/prompt.py +358 -0
- superqode/widgets/provider_connect.py +725 -0
- superqode/widgets/pty_shell.py +587 -0
- superqode/widgets/qe_dashboard.py +321 -0
- superqode/widgets/resizable_sidebar.py +377 -0
- superqode/widgets/response_changes.py +218 -0
- superqode/widgets/response_display.py +528 -0
- superqode/widgets/rich_tool_display.py +613 -0
- superqode/widgets/sidebar_panels.py +1180 -0
- superqode/widgets/slash_complete.py +356 -0
- superqode/widgets/split_view.py +612 -0
- superqode/widgets/status_bar.py +273 -0
- superqode/widgets/superqode_display.py +786 -0
- superqode/widgets/thinking_display.py +815 -0
- superqode/widgets/throbber.py +87 -0
- superqode/widgets/toast.py +206 -0
- superqode/widgets/unified_output.py +1073 -0
- superqode/workspace/__init__.py +75 -0
- superqode/workspace/artifacts.py +472 -0
- superqode/workspace/coordinator.py +353 -0
- superqode/workspace/diff_tracker.py +429 -0
- superqode/workspace/git_guard.py +373 -0
- superqode/workspace/git_snapshot.py +526 -0
- superqode/workspace/manager.py +750 -0
- superqode/workspace/snapshot.py +357 -0
- superqode/workspace/watcher.py +535 -0
- superqode/workspace/worktree.py +440 -0
- superqode-0.1.5.dist-info/METADATA +204 -0
- superqode-0.1.5.dist-info/RECORD +288 -0
- superqode-0.1.5.dist-info/WHEEL +5 -0
- superqode-0.1.5.dist-info/entry_points.txt +3 -0
- superqode-0.1.5.dist-info/licenses/LICENSE +648 -0
- superqode-0.1.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Message ↔ Item Conversion.
|
|
3
|
+
|
|
4
|
+
Bidirectional conversion between OpenAI-style messages and Open Responses items.
|
|
5
|
+
|
|
6
|
+
OpenAI Format (messages):
|
|
7
|
+
[
|
|
8
|
+
{"role": "user", "content": "Hello"},
|
|
9
|
+
{"role": "assistant", "content": "Hi!", "tool_calls": [...]},
|
|
10
|
+
{"role": "tool", "tool_call_id": "call_123", "content": "result"}
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
Open Responses Format (items):
|
|
14
|
+
[
|
|
15
|
+
{"type": "message", "role": "user", "content": "Hello"},
|
|
16
|
+
{"type": "message", "role": "assistant", "content": [...]},
|
|
17
|
+
{"type": "function_call", "call_id": "call_123", "name": "tool", "arguments": "{}"},
|
|
18
|
+
{"type": "function_call_output", "call_id": "call_123", "output": "result"}
|
|
19
|
+
]
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
from typing import Any, Dict, List, Optional, Union
|
|
26
|
+
|
|
27
|
+
from ..schema.models import (
|
|
28
|
+
ItemParam,
|
|
29
|
+
UserMessageItemParam,
|
|
30
|
+
AssistantMessageItemParam,
|
|
31
|
+
SystemMessageItemParam,
|
|
32
|
+
FunctionCallItemParam,
|
|
33
|
+
FunctionCallOutputItemParam,
|
|
34
|
+
TextContentParam,
|
|
35
|
+
ImageContentParam,
|
|
36
|
+
)
|
|
37
|
+
from ...gateway.base import Message
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def messages_to_items(messages: List[Message]) -> List[Dict[str, Any]]:
|
|
41
|
+
"""
|
|
42
|
+
Convert OpenAI-style messages to Open Responses items.
|
|
43
|
+
|
|
44
|
+
Handles:
|
|
45
|
+
- User messages → UserMessageItemParam
|
|
46
|
+
- Assistant messages → AssistantMessageItemParam + FunctionCallItemParam (if tool_calls)
|
|
47
|
+
- System messages → SystemMessageItemParam
|
|
48
|
+
- Tool messages → FunctionCallOutputItemParam
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
messages: List of Message objects
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
List of Open Responses item dicts
|
|
55
|
+
"""
|
|
56
|
+
items: List[Dict[str, Any]] = []
|
|
57
|
+
|
|
58
|
+
for msg in messages:
|
|
59
|
+
role = msg.role
|
|
60
|
+
content = msg.content
|
|
61
|
+
|
|
62
|
+
if role == "system":
|
|
63
|
+
items.append(
|
|
64
|
+
{
|
|
65
|
+
"type": "message",
|
|
66
|
+
"role": "system",
|
|
67
|
+
"content": content,
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
elif role == "user":
|
|
72
|
+
items.append(
|
|
73
|
+
{
|
|
74
|
+
"type": "message",
|
|
75
|
+
"role": "user",
|
|
76
|
+
"content": _convert_content_to_items(content),
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
elif role == "assistant":
|
|
81
|
+
# Assistant message - may include tool calls
|
|
82
|
+
if content:
|
|
83
|
+
items.append(
|
|
84
|
+
{
|
|
85
|
+
"type": "message",
|
|
86
|
+
"role": "assistant",
|
|
87
|
+
"content": _convert_content_to_items(content),
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Convert tool calls to function_call items
|
|
92
|
+
if msg.tool_calls:
|
|
93
|
+
for tc in msg.tool_calls:
|
|
94
|
+
func = tc.get("function", {})
|
|
95
|
+
items.append(
|
|
96
|
+
{
|
|
97
|
+
"type": "function_call",
|
|
98
|
+
"call_id": tc.get("id", ""),
|
|
99
|
+
"name": func.get("name", ""),
|
|
100
|
+
"arguments": func.get("arguments", "{}"),
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
elif role == "tool":
|
|
105
|
+
# Tool result → function_call_output
|
|
106
|
+
items.append(
|
|
107
|
+
{
|
|
108
|
+
"type": "function_call_output",
|
|
109
|
+
"call_id": msg.tool_call_id or "",
|
|
110
|
+
"output": content,
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
return items
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def items_to_messages(items: List[Dict[str, Any]]) -> List[Message]:
|
|
118
|
+
"""
|
|
119
|
+
Convert Open Responses items to OpenAI-style messages.
|
|
120
|
+
|
|
121
|
+
Handles:
|
|
122
|
+
- message items → Message objects
|
|
123
|
+
- function_call items → Assistant message with tool_calls
|
|
124
|
+
- function_call_output items → Tool message
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
items: List of Open Responses item dicts
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
List of Message objects
|
|
131
|
+
"""
|
|
132
|
+
messages: List[Message] = []
|
|
133
|
+
pending_tool_calls: List[Dict[str, Any]] = []
|
|
134
|
+
|
|
135
|
+
for item in items:
|
|
136
|
+
item_type = item.get("type", "")
|
|
137
|
+
|
|
138
|
+
if item_type == "message":
|
|
139
|
+
# Flush any pending tool calls first
|
|
140
|
+
if pending_tool_calls:
|
|
141
|
+
messages.append(
|
|
142
|
+
Message(
|
|
143
|
+
role="assistant",
|
|
144
|
+
content="",
|
|
145
|
+
tool_calls=pending_tool_calls,
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
pending_tool_calls = []
|
|
149
|
+
|
|
150
|
+
role = item.get("role", "user")
|
|
151
|
+
content = _convert_items_to_content(item.get("content", ""))
|
|
152
|
+
|
|
153
|
+
messages.append(
|
|
154
|
+
Message(
|
|
155
|
+
role=role,
|
|
156
|
+
content=content,
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
elif item_type == "function_call":
|
|
161
|
+
# Accumulate tool calls for the assistant message
|
|
162
|
+
pending_tool_calls.append(
|
|
163
|
+
{
|
|
164
|
+
"id": item.get("call_id", ""),
|
|
165
|
+
"type": "function",
|
|
166
|
+
"function": {
|
|
167
|
+
"name": item.get("name", ""),
|
|
168
|
+
"arguments": item.get("arguments", "{}"),
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
elif item_type == "function_call_output":
|
|
174
|
+
# Flush any pending tool calls first
|
|
175
|
+
if pending_tool_calls:
|
|
176
|
+
messages.append(
|
|
177
|
+
Message(
|
|
178
|
+
role="assistant",
|
|
179
|
+
content="",
|
|
180
|
+
tool_calls=pending_tool_calls,
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
pending_tool_calls = []
|
|
184
|
+
|
|
185
|
+
# Tool result
|
|
186
|
+
messages.append(
|
|
187
|
+
Message(
|
|
188
|
+
role="tool",
|
|
189
|
+
content=item.get("output", ""),
|
|
190
|
+
tool_call_id=item.get("call_id", ""),
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
# Flush any remaining pending tool calls
|
|
195
|
+
if pending_tool_calls:
|
|
196
|
+
messages.append(
|
|
197
|
+
Message(
|
|
198
|
+
role="assistant",
|
|
199
|
+
content="",
|
|
200
|
+
tool_calls=pending_tool_calls,
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
return messages
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _convert_content_to_items(content: Union[str, List[Any]]) -> Union[str, List[Dict[str, Any]]]:
|
|
208
|
+
"""
|
|
209
|
+
Convert message content to Open Responses format.
|
|
210
|
+
|
|
211
|
+
Handles both string content and multi-part content (images, etc.).
|
|
212
|
+
"""
|
|
213
|
+
if isinstance(content, str):
|
|
214
|
+
return content
|
|
215
|
+
|
|
216
|
+
if isinstance(content, list):
|
|
217
|
+
items = []
|
|
218
|
+
for part in content:
|
|
219
|
+
if isinstance(part, str):
|
|
220
|
+
items.append({"type": "input_text", "text": part})
|
|
221
|
+
elif isinstance(part, dict):
|
|
222
|
+
part_type = part.get("type", "")
|
|
223
|
+
if part_type == "text":
|
|
224
|
+
items.append({"type": "input_text", "text": part.get("text", "")})
|
|
225
|
+
elif part_type == "image_url":
|
|
226
|
+
image_url = part.get("image_url", {})
|
|
227
|
+
url = image_url.get("url", "") if isinstance(image_url, dict) else image_url
|
|
228
|
+
items.append(
|
|
229
|
+
{
|
|
230
|
+
"type": "input_image",
|
|
231
|
+
"image_url": url,
|
|
232
|
+
"detail": image_url.get("detail", "auto")
|
|
233
|
+
if isinstance(image_url, dict)
|
|
234
|
+
else "auto",
|
|
235
|
+
}
|
|
236
|
+
)
|
|
237
|
+
else:
|
|
238
|
+
# Pass through unknown types
|
|
239
|
+
items.append(part)
|
|
240
|
+
return items
|
|
241
|
+
|
|
242
|
+
return str(content)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _convert_items_to_content(content: Union[str, List[Any]]) -> str:
|
|
246
|
+
"""
|
|
247
|
+
Convert Open Responses content items to string content.
|
|
248
|
+
|
|
249
|
+
For simplicity, concatenates all text parts.
|
|
250
|
+
Image handling would require additional logic in the caller.
|
|
251
|
+
"""
|
|
252
|
+
if isinstance(content, str):
|
|
253
|
+
return content
|
|
254
|
+
|
|
255
|
+
if isinstance(content, list):
|
|
256
|
+
text_parts = []
|
|
257
|
+
for part in content:
|
|
258
|
+
if isinstance(part, str):
|
|
259
|
+
text_parts.append(part)
|
|
260
|
+
elif isinstance(part, dict):
|
|
261
|
+
part_type = part.get("type", "")
|
|
262
|
+
if part_type in ("text", "input_text", "output_text"):
|
|
263
|
+
text_parts.append(part.get("text", ""))
|
|
264
|
+
elif part_type == "refusal":
|
|
265
|
+
text_parts.append(f"[Refusal: {part.get('refusal', '')}]")
|
|
266
|
+
return "".join(text_parts)
|
|
267
|
+
|
|
268
|
+
return str(content)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def convert_output_to_message(output_items: List[Dict[str, Any]]) -> Message:
|
|
272
|
+
"""
|
|
273
|
+
Convert Open Responses output items to a single assistant message.
|
|
274
|
+
|
|
275
|
+
Extracts text content and tool calls from the output.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
output_items: List of output items from a Response
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
Message object with content and optional tool_calls
|
|
282
|
+
"""
|
|
283
|
+
content_parts: List[str] = []
|
|
284
|
+
tool_calls: List[Dict[str, Any]] = []
|
|
285
|
+
|
|
286
|
+
for item in output_items:
|
|
287
|
+
item_type = item.get("type", "")
|
|
288
|
+
|
|
289
|
+
if item_type == "message":
|
|
290
|
+
# Extract text from message content
|
|
291
|
+
item_content = item.get("content", [])
|
|
292
|
+
if isinstance(item_content, str):
|
|
293
|
+
content_parts.append(item_content)
|
|
294
|
+
elif isinstance(item_content, list):
|
|
295
|
+
for part in item_content:
|
|
296
|
+
if isinstance(part, dict):
|
|
297
|
+
part_type = part.get("type", "")
|
|
298
|
+
if part_type in ("text", "output_text"):
|
|
299
|
+
content_parts.append(part.get("text", ""))
|
|
300
|
+
elif part_type == "reasoning":
|
|
301
|
+
# Skip reasoning in main content
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
elif item_type == "function_call":
|
|
305
|
+
tool_calls.append(
|
|
306
|
+
{
|
|
307
|
+
"id": item.get("call_id", item.get("id", "")),
|
|
308
|
+
"type": "function",
|
|
309
|
+
"function": {
|
|
310
|
+
"name": item.get("name", ""),
|
|
311
|
+
"arguments": item.get("arguments", "{}"),
|
|
312
|
+
},
|
|
313
|
+
}
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
return Message(
|
|
317
|
+
role="assistant",
|
|
318
|
+
content="".join(content_parts),
|
|
319
|
+
tool_calls=tool_calls if tool_calls else None,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def extract_reasoning_from_output(output_items: List[Dict[str, Any]]) -> Optional[str]:
|
|
324
|
+
"""
|
|
325
|
+
Extract reasoning/thinking content from Open Responses output.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
output_items: List of output items from a Response
|
|
329
|
+
|
|
330
|
+
Returns:
|
|
331
|
+
Reasoning text if found, None otherwise
|
|
332
|
+
"""
|
|
333
|
+
reasoning_parts: List[str] = []
|
|
334
|
+
|
|
335
|
+
for item in output_items:
|
|
336
|
+
if item.get("type") == "message":
|
|
337
|
+
item_content = item.get("content", [])
|
|
338
|
+
if isinstance(item_content, list):
|
|
339
|
+
for part in item_content:
|
|
340
|
+
if isinstance(part, dict) and part.get("type") == "reasoning":
|
|
341
|
+
reasoning_parts.append(part.get("text", ""))
|
|
342
|
+
|
|
343
|
+
return "".join(reasoning_parts) if reasoning_parts else None
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tool Definition Conversion.
|
|
3
|
+
|
|
4
|
+
Converts between Gateway ToolDefinition and Open Responses tool formats.
|
|
5
|
+
|
|
6
|
+
Gateway Format:
|
|
7
|
+
ToolDefinition(
|
|
8
|
+
name="read_file",
|
|
9
|
+
description="Read a file",
|
|
10
|
+
parameters={"type": "object", "properties": {...}}
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
Open Responses Format:
|
|
14
|
+
{
|
|
15
|
+
"type": "function",
|
|
16
|
+
"function": {
|
|
17
|
+
"name": "read_file",
|
|
18
|
+
"description": "Read a file",
|
|
19
|
+
"parameters": {"type": "object", "properties": {...}}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from typing import Any, Dict, List, Optional
|
|
27
|
+
|
|
28
|
+
from ...gateway.base import ToolDefinition
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def convert_tools_to_openresponses(tools: Optional[List[ToolDefinition]]) -> List[Dict[str, Any]]:
|
|
32
|
+
"""
|
|
33
|
+
Convert Gateway tool definitions to Open Responses format.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
tools: List of ToolDefinition objects
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
List of Open Responses tool dicts
|
|
40
|
+
"""
|
|
41
|
+
if not tools:
|
|
42
|
+
return []
|
|
43
|
+
|
|
44
|
+
result = []
|
|
45
|
+
for tool in tools:
|
|
46
|
+
result.append(
|
|
47
|
+
{
|
|
48
|
+
"type": "function",
|
|
49
|
+
"function": {
|
|
50
|
+
"name": tool.name,
|
|
51
|
+
"description": tool.description,
|
|
52
|
+
"parameters": tool.parameters,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return result
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def convert_tools_from_openresponses(tools: Optional[List[Dict[str, Any]]]) -> List[ToolDefinition]:
|
|
61
|
+
"""
|
|
62
|
+
Convert Open Responses tools to Gateway ToolDefinition objects.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
tools: List of Open Responses tool dicts
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
List of ToolDefinition objects
|
|
69
|
+
"""
|
|
70
|
+
if not tools:
|
|
71
|
+
return []
|
|
72
|
+
|
|
73
|
+
result = []
|
|
74
|
+
for tool in tools:
|
|
75
|
+
tool_type = tool.get("type", "")
|
|
76
|
+
|
|
77
|
+
if tool_type == "function":
|
|
78
|
+
func = tool.get("function", {})
|
|
79
|
+
result.append(
|
|
80
|
+
ToolDefinition(
|
|
81
|
+
name=func.get("name", ""),
|
|
82
|
+
description=func.get("description", ""),
|
|
83
|
+
parameters=func.get("parameters", {}),
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
elif tool_type == "code_interpreter":
|
|
88
|
+
# Built-in tool - create a placeholder definition
|
|
89
|
+
result.append(
|
|
90
|
+
ToolDefinition(
|
|
91
|
+
name="code_interpreter",
|
|
92
|
+
description="Execute code in a sandboxed environment",
|
|
93
|
+
parameters={
|
|
94
|
+
"type": "object",
|
|
95
|
+
"properties": {
|
|
96
|
+
"code": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"description": "The code to execute",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
"required": ["code"],
|
|
102
|
+
},
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
elif tool_type == "file_search":
|
|
107
|
+
# Built-in tool
|
|
108
|
+
result.append(
|
|
109
|
+
ToolDefinition(
|
|
110
|
+
name="file_search",
|
|
111
|
+
description="Search files in vector stores",
|
|
112
|
+
parameters={
|
|
113
|
+
"type": "object",
|
|
114
|
+
"properties": {
|
|
115
|
+
"query": {
|
|
116
|
+
"type": "string",
|
|
117
|
+
"description": "The search query",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
"required": ["query"],
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
elif tool_type == "apply_patch":
|
|
126
|
+
# Built-in tool
|
|
127
|
+
result.append(
|
|
128
|
+
ToolDefinition(
|
|
129
|
+
name="apply_patch",
|
|
130
|
+
description="Apply a patch to files",
|
|
131
|
+
parameters={
|
|
132
|
+
"type": "object",
|
|
133
|
+
"properties": {
|
|
134
|
+
"patch": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"description": "The patch to apply in unified diff format",
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
"required": ["patch"],
|
|
140
|
+
},
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
elif tool_type == "web_search":
|
|
145
|
+
# Built-in tool
|
|
146
|
+
result.append(
|
|
147
|
+
ToolDefinition(
|
|
148
|
+
name="web_search",
|
|
149
|
+
description="Search the web for information",
|
|
150
|
+
parameters={
|
|
151
|
+
"type": "object",
|
|
152
|
+
"properties": {
|
|
153
|
+
"query": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"description": "The search query",
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
"required": ["query"],
|
|
159
|
+
},
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
return result
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def create_openresponses_function_tool(
|
|
167
|
+
name: str,
|
|
168
|
+
description: str,
|
|
169
|
+
parameters: Dict[str, Any],
|
|
170
|
+
strict: bool = False,
|
|
171
|
+
) -> Dict[str, Any]:
|
|
172
|
+
"""
|
|
173
|
+
Create an Open Responses function tool definition.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
name: Tool name
|
|
177
|
+
description: Tool description
|
|
178
|
+
parameters: JSON Schema for parameters
|
|
179
|
+
strict: Enable strict mode for structured outputs
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Open Responses tool dict
|
|
183
|
+
"""
|
|
184
|
+
return {
|
|
185
|
+
"type": "function",
|
|
186
|
+
"function": {
|
|
187
|
+
"name": name,
|
|
188
|
+
"description": description,
|
|
189
|
+
"parameters": parameters,
|
|
190
|
+
"strict": strict,
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def create_code_interpreter_tool(container: Optional[str] = None) -> Dict[str, Any]:
|
|
196
|
+
"""
|
|
197
|
+
Create an Open Responses code interpreter tool.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
container: Optional container configuration
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
Open Responses tool dict
|
|
204
|
+
"""
|
|
205
|
+
tool = {"type": "code_interpreter"}
|
|
206
|
+
if container:
|
|
207
|
+
tool["container"] = container
|
|
208
|
+
return tool
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def create_file_search_tool(
|
|
212
|
+
vector_store_ids: Optional[List[str]] = None,
|
|
213
|
+
max_num_results: int = 20,
|
|
214
|
+
ranking_options: Optional[Dict[str, Any]] = None,
|
|
215
|
+
) -> Dict[str, Any]:
|
|
216
|
+
"""
|
|
217
|
+
Create an Open Responses file search tool.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
vector_store_ids: List of vector store IDs to search
|
|
221
|
+
max_num_results: Maximum number of results
|
|
222
|
+
ranking_options: Ranking configuration
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
Open Responses tool dict
|
|
226
|
+
"""
|
|
227
|
+
tool: Dict[str, Any] = {
|
|
228
|
+
"type": "file_search",
|
|
229
|
+
"max_num_results": max_num_results,
|
|
230
|
+
}
|
|
231
|
+
if vector_store_ids:
|
|
232
|
+
tool["vector_store_ids"] = vector_store_ids
|
|
233
|
+
if ranking_options:
|
|
234
|
+
tool["ranking_options"] = ranking_options
|
|
235
|
+
return tool
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def create_apply_patch_tool() -> Dict[str, Any]:
|
|
239
|
+
"""
|
|
240
|
+
Create an Open Responses apply patch tool.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
Open Responses tool dict
|
|
244
|
+
"""
|
|
245
|
+
return {"type": "apply_patch"}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def create_web_search_tool(
|
|
249
|
+
search_context_size: str = "medium",
|
|
250
|
+
user_location: Optional[Dict[str, Any]] = None,
|
|
251
|
+
) -> Dict[str, Any]:
|
|
252
|
+
"""
|
|
253
|
+
Create an Open Responses web search tool.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
search_context_size: Size of search context ("low", "medium", "high")
|
|
257
|
+
user_location: Optional user location for localized results
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
Open Responses tool dict
|
|
261
|
+
"""
|
|
262
|
+
tool: Dict[str, Any] = {
|
|
263
|
+
"type": "web_search",
|
|
264
|
+
"search_context_size": search_context_size,
|
|
265
|
+
}
|
|
266
|
+
if user_location:
|
|
267
|
+
tool["user_location"] = user_location
|
|
268
|
+
return tool
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Open Responses schema types."""
|
|
2
|
+
|
|
3
|
+
from .models import (
|
|
4
|
+
# Request/Response types
|
|
5
|
+
ResponseRequest,
|
|
6
|
+
Response,
|
|
7
|
+
ResponseUsage,
|
|
8
|
+
# Item types
|
|
9
|
+
ItemParam,
|
|
10
|
+
UserMessageItemParam,
|
|
11
|
+
AssistantMessageItemParam,
|
|
12
|
+
SystemMessageItemParam,
|
|
13
|
+
FunctionCallItemParam,
|
|
14
|
+
FunctionCallOutputItemParam,
|
|
15
|
+
# Content types
|
|
16
|
+
TextContentParam,
|
|
17
|
+
ImageContentParam,
|
|
18
|
+
# Tool types
|
|
19
|
+
FunctionToolParam,
|
|
20
|
+
CodeInterpreterToolParam,
|
|
21
|
+
FileSearchToolParam,
|
|
22
|
+
ApplyPatchToolParam,
|
|
23
|
+
# Streaming events
|
|
24
|
+
StreamingEvent,
|
|
25
|
+
ResponseCreatedEvent,
|
|
26
|
+
ResponseInProgressEvent,
|
|
27
|
+
ResponseCompletedEvent,
|
|
28
|
+
ResponseOutputTextDeltaEvent,
|
|
29
|
+
ResponseReasoningDeltaEvent,
|
|
30
|
+
ResponseFunctionCallArgumentsDeltaEvent,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"ResponseRequest",
|
|
35
|
+
"Response",
|
|
36
|
+
"ResponseUsage",
|
|
37
|
+
"ItemParam",
|
|
38
|
+
"UserMessageItemParam",
|
|
39
|
+
"AssistantMessageItemParam",
|
|
40
|
+
"SystemMessageItemParam",
|
|
41
|
+
"FunctionCallItemParam",
|
|
42
|
+
"FunctionCallOutputItemParam",
|
|
43
|
+
"TextContentParam",
|
|
44
|
+
"ImageContentParam",
|
|
45
|
+
"FunctionToolParam",
|
|
46
|
+
"CodeInterpreterToolParam",
|
|
47
|
+
"FileSearchToolParam",
|
|
48
|
+
"ApplyPatchToolParam",
|
|
49
|
+
"StreamingEvent",
|
|
50
|
+
"ResponseCreatedEvent",
|
|
51
|
+
"ResponseInProgressEvent",
|
|
52
|
+
"ResponseCompletedEvent",
|
|
53
|
+
"ResponseOutputTextDeltaEvent",
|
|
54
|
+
"ResponseReasoningDeltaEvent",
|
|
55
|
+
"ResponseFunctionCallArgumentsDeltaEvent",
|
|
56
|
+
]
|