pygpt-net 2.7.4__py3-none-any.whl → 2.7.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.
- pygpt_net/CHANGELOG.txt +7 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app_core.py +4 -2
- pygpt_net/controller/__init__.py +5 -1
- pygpt_net/controller/assistant/assistant.py +1 -4
- pygpt_net/controller/assistant/batch.py +5 -504
- pygpt_net/controller/assistant/editor.py +5 -5
- pygpt_net/controller/assistant/files.py +16 -16
- pygpt_net/controller/chat/handler/google_stream.py +307 -1
- pygpt_net/controller/chat/handler/worker.py +8 -1
- pygpt_net/controller/chat/image.py +2 -2
- pygpt_net/controller/dialogs/confirm.py +73 -101
- pygpt_net/controller/lang/mapping.py +9 -9
- pygpt_net/controller/painter/capture.py +50 -1
- pygpt_net/controller/presets/presets.py +2 -1
- pygpt_net/controller/remote_store/__init__.py +12 -0
- pygpt_net/{provider/core/assistant_file/db_sqlite → controller/remote_store/google}/__init__.py +2 -2
- pygpt_net/controller/remote_store/google/batch.py +402 -0
- pygpt_net/controller/remote_store/google/store.py +615 -0
- pygpt_net/controller/remote_store/openai/__init__.py +12 -0
- pygpt_net/controller/remote_store/openai/batch.py +524 -0
- pygpt_net/controller/{assistant → remote_store/openai}/store.py +63 -60
- pygpt_net/controller/remote_store/remote_store.py +35 -0
- pygpt_net/controller/ui/ui.py +20 -1
- pygpt_net/core/assistants/assistants.py +3 -15
- pygpt_net/core/db/database.py +5 -3
- pygpt_net/core/locale/placeholder.py +35 -0
- pygpt_net/core/remote_store/__init__.py +12 -0
- pygpt_net/core/remote_store/google/__init__.py +11 -0
- pygpt_net/core/remote_store/google/files.py +224 -0
- pygpt_net/core/remote_store/google/store.py +248 -0
- pygpt_net/core/remote_store/openai/__init__.py +11 -0
- pygpt_net/core/{assistants → remote_store/openai}/files.py +26 -19
- pygpt_net/core/{assistants → remote_store/openai}/store.py +32 -15
- pygpt_net/core/remote_store/remote_store.py +24 -0
- pygpt_net/data/config/config.json +8 -4
- pygpt_net/data/config/models.json +77 -3
- pygpt_net/data/config/settings.json +45 -0
- pygpt_net/data/locale/locale.de.ini +41 -41
- pygpt_net/data/locale/locale.en.ini +53 -43
- pygpt_net/data/locale/locale.es.ini +41 -41
- pygpt_net/data/locale/locale.fr.ini +41 -41
- pygpt_net/data/locale/locale.it.ini +41 -41
- pygpt_net/data/locale/locale.pl.ini +42 -42
- pygpt_net/data/locale/locale.uk.ini +41 -41
- pygpt_net/data/locale/locale.zh.ini +41 -41
- pygpt_net/data/locale/plugin.cmd_history.de.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.en.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.es.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.fr.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.it.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.pl.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.uk.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.zh.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_mouse_control.en.ini +14 -0
- pygpt_net/data/locale/plugin.cmd_web.de.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.en.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.es.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.fr.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.it.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.pl.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.uk.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.zh.ini +1 -1
- pygpt_net/data/locale/plugin.idx_llama_index.de.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.en.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.es.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.it.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +2 -2
- pygpt_net/item/assistant.py +1 -211
- pygpt_net/item/ctx.py +3 -1
- pygpt_net/item/store.py +238 -0
- pygpt_net/migrations/Version20260102190000.py +35 -0
- pygpt_net/migrations/__init__.py +3 -1
- pygpt_net/plugin/cmd_mouse_control/config.py +470 -1
- pygpt_net/plugin/cmd_mouse_control/plugin.py +488 -22
- pygpt_net/plugin/cmd_mouse_control/worker.py +464 -87
- pygpt_net/plugin/cmd_mouse_control/worker_sandbox.py +729 -0
- pygpt_net/plugin/idx_llama_index/config.py +2 -2
- pygpt_net/provider/api/google/__init__.py +16 -54
- pygpt_net/provider/api/google/chat.py +546 -129
- pygpt_net/provider/api/google/computer.py +190 -0
- pygpt_net/provider/api/google/realtime/realtime.py +2 -2
- pygpt_net/provider/api/google/remote_tools.py +93 -0
- pygpt_net/provider/api/google/store.py +546 -0
- pygpt_net/provider/api/google/worker/__init__.py +0 -0
- pygpt_net/provider/api/google/worker/importer.py +392 -0
- pygpt_net/provider/api/openai/computer.py +10 -1
- pygpt_net/provider/api/openai/store.py +6 -6
- pygpt_net/provider/api/openai/worker/importer.py +24 -24
- pygpt_net/provider/core/config/patch.py +16 -1
- pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +3 -3
- pygpt_net/provider/core/model/patch.py +17 -3
- pygpt_net/provider/core/preset/json_file.py +13 -7
- pygpt_net/provider/core/{assistant_file → remote_file}/__init__.py +1 -1
- pygpt_net/provider/core/{assistant_file → remote_file}/base.py +9 -9
- pygpt_net/provider/core/remote_file/db_sqlite/__init__.py +12 -0
- pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/patch.py +1 -1
- pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/provider.py +23 -20
- pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/storage.py +35 -27
- pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/utils.py +5 -4
- pygpt_net/provider/core/{assistant_store → remote_store}/__init__.py +1 -1
- pygpt_net/provider/core/{assistant_store → remote_store}/base.py +10 -10
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/__init__.py +1 -1
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/patch.py +1 -1
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/provider.py +16 -15
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/storage.py +30 -23
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/utils.py +5 -4
- pygpt_net/provider/core/{assistant_store → remote_store}/json_file.py +9 -9
- pygpt_net/provider/llms/google.py +2 -2
- pygpt_net/ui/base/config_dialog.py +3 -2
- pygpt_net/ui/dialog/assistant.py +3 -3
- pygpt_net/ui/dialog/plugins.py +3 -1
- pygpt_net/ui/dialog/remote_store_google.py +539 -0
- pygpt_net/ui/dialog/{assistant_store.py → remote_store_openai.py} +95 -95
- pygpt_net/ui/dialogs.py +5 -3
- pygpt_net/ui/layout/chat/attachments_uploaded.py +3 -3
- pygpt_net/ui/layout/toolbox/computer_env.py +26 -8
- pygpt_net/ui/menu/tools.py +13 -5
- pygpt_net/ui/widget/dialog/remote_store_google.py +56 -0
- pygpt_net/ui/widget/dialog/{assistant_store.py → remote_store_openai.py} +9 -9
- pygpt_net/ui/widget/element/button.py +4 -4
- pygpt_net/ui/widget/lists/remote_store_google.py +248 -0
- pygpt_net/ui/widget/lists/{assistant_store.py → remote_store_openai.py} +21 -21
- pygpt_net/ui/widget/option/checkbox_list.py +47 -9
- pygpt_net/ui/widget/option/combo.py +39 -3
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/METADATA +33 -2
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/RECORD +133 -108
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/LICENSE +0 -0
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/WHEEL +0 -0
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# ================================================== #
|
|
4
|
+
# This file is a part of PYGPT package #
|
|
5
|
+
# Website: https://pygpt.net #
|
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
|
+
# MIT License #
|
|
8
|
+
# Created By : Marcin Szczyglinski #
|
|
9
|
+
# Updated Date: 2026.01.02 02:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import time
|
|
14
|
+
from typing import Dict, Any, List, Tuple, Optional
|
|
15
|
+
|
|
16
|
+
from google.genai import types as gtypes
|
|
17
|
+
from pygpt_net.item.ctx import CtxItem
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Computer:
|
|
21
|
+
def __init__(self, window=None):
|
|
22
|
+
"""
|
|
23
|
+
Google Gemini Computer Use adapter
|
|
24
|
+
|
|
25
|
+
This adapter passes Google Gemini function calls and action events
|
|
26
|
+
directly to the plugin worker without translating names to legacy
|
|
27
|
+
commands. The workers (host and sandbox) implement the full set
|
|
28
|
+
of functions and handle any coordinate conversions themselves.
|
|
29
|
+
"""
|
|
30
|
+
self.window = window
|
|
31
|
+
self._seq = 0
|
|
32
|
+
|
|
33
|
+
# --------------- Tool spec --------------- #
|
|
34
|
+
|
|
35
|
+
def get_current_env(self) -> Dict[str, Any]:
|
|
36
|
+
idx = self.window.ui.nodes["computer_env"].currentIndex()
|
|
37
|
+
return self.window.ui.nodes["computer_env"].itemData(idx)
|
|
38
|
+
|
|
39
|
+
def _map_env(self) -> gtypes.Environment:
|
|
40
|
+
return gtypes.Environment.ENVIRONMENT_BROWSER
|
|
41
|
+
env = self.get_current_env()
|
|
42
|
+
val = ""
|
|
43
|
+
if isinstance(env, str):
|
|
44
|
+
val = env.lower()
|
|
45
|
+
elif isinstance(env, dict):
|
|
46
|
+
val = str(env.get("value") or env.get("name") or env).lower()
|
|
47
|
+
if "mac" in val:
|
|
48
|
+
return gtypes.Environment.ENVIRONMENT_MAC
|
|
49
|
+
if "windows" in val or "win" in val:
|
|
50
|
+
return gtypes.Environment.ENVIRONMENT_WINDOWS
|
|
51
|
+
if "linux" in val:
|
|
52
|
+
return gtypes.Environment.ENVIRONMENT_LINUX
|
|
53
|
+
return gtypes.Environment.ENVIRONMENT_BROWSER
|
|
54
|
+
|
|
55
|
+
def get_tool(self) -> gtypes.Tool:
|
|
56
|
+
return gtypes.Tool(
|
|
57
|
+
computer_use=gtypes.ComputerUse(
|
|
58
|
+
environment=self._map_env(),
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# --------------- Streaming handling --------------- #
|
|
63
|
+
|
|
64
|
+
def _next_id(self) -> str:
|
|
65
|
+
self._seq += 1
|
|
66
|
+
return f"gc-{int(time.time()*1000)}-{self._seq}"
|
|
67
|
+
|
|
68
|
+
def _append_call(self, tool_calls: list, id_: str, call_id: str, name: str, args: dict) -> None:
|
|
69
|
+
tool_calls.append({
|
|
70
|
+
"id": id_,
|
|
71
|
+
"call_id": call_id,
|
|
72
|
+
"type": "computer_call",
|
|
73
|
+
"function": {
|
|
74
|
+
"name": name,
|
|
75
|
+
"arguments": json.dumps(args or {}),
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
def _append_screenshot(self, tool_calls: list, id_: str, call_id: str) -> None:
|
|
80
|
+
self._append_call(tool_calls, id_, call_id, "get_screenshot", {})
|
|
81
|
+
|
|
82
|
+
def _record_pending_checks(self, ctx: CtxItem, pending: Optional[list]) -> None:
|
|
83
|
+
if not pending:
|
|
84
|
+
return
|
|
85
|
+
ctx.extra["pending_safety_checks"] = []
|
|
86
|
+
for item in pending:
|
|
87
|
+
try:
|
|
88
|
+
ctx.extra["pending_safety_checks"].append({
|
|
89
|
+
"id": getattr(item, "id", None),
|
|
90
|
+
"code": getattr(item, "code", None),
|
|
91
|
+
"message": getattr(item, "message", None),
|
|
92
|
+
})
|
|
93
|
+
except Exception:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
def handle_stream_chunk(self, ctx: CtxItem, chunk, tool_calls: list) -> Tuple[List, bool]:
|
|
97
|
+
"""
|
|
98
|
+
Handle function_call parts (Gemini) and older action-shaped events.
|
|
99
|
+
All functions are passed through unchanged to the worker.
|
|
100
|
+
|
|
101
|
+
Returns: updated tool_calls and a boolean indicating if there were calls.
|
|
102
|
+
"""
|
|
103
|
+
has_calls = False
|
|
104
|
+
|
|
105
|
+
# Case A: Google SDK function_call parts (recommended)
|
|
106
|
+
for fname, fargs in self._iter_function_calls(chunk):
|
|
107
|
+
if not fname:
|
|
108
|
+
continue
|
|
109
|
+
id_ = self._next_id()
|
|
110
|
+
call_id = id_
|
|
111
|
+
try:
|
|
112
|
+
self._append_call(tool_calls, id_, call_id, fname, fargs or {})
|
|
113
|
+
has_calls = True
|
|
114
|
+
except Exception as e:
|
|
115
|
+
print(f"Gemini pass-through error for function '{fname}': {e}")
|
|
116
|
+
|
|
117
|
+
# Case B: Older/OpenAI-shaped events embedded as chunk.item.action
|
|
118
|
+
try:
|
|
119
|
+
item = getattr(chunk, "item", None)
|
|
120
|
+
if item and getattr(item, "type", "") == "computer_call":
|
|
121
|
+
id_ = getattr(item, "id", None) or self._next_id()
|
|
122
|
+
call_id = getattr(item, "call_id", None) or id_
|
|
123
|
+
action = getattr(item, "action", None)
|
|
124
|
+
if action:
|
|
125
|
+
name, args = self._pass_action(action)
|
|
126
|
+
if name:
|
|
127
|
+
self._append_call(tool_calls, id_, call_id, name, args)
|
|
128
|
+
has_calls = True
|
|
129
|
+
# optional pending safety checks
|
|
130
|
+
if getattr(item, "pending_safety_checks", None):
|
|
131
|
+
self._record_pending_checks(ctx, item.pending_safety_checks)
|
|
132
|
+
except Exception as e:
|
|
133
|
+
print(f"Gemini action stream parse error: {e}")
|
|
134
|
+
|
|
135
|
+
return tool_calls, has_calls
|
|
136
|
+
|
|
137
|
+
# --------------- Parsers --------------- #
|
|
138
|
+
|
|
139
|
+
def _iter_function_calls(self, resp) -> List[tuple]:
|
|
140
|
+
calls = []
|
|
141
|
+
try:
|
|
142
|
+
candidates = getattr(resp, "candidates", None)
|
|
143
|
+
if candidates:
|
|
144
|
+
for cand in candidates:
|
|
145
|
+
content = getattr(cand, "content", None)
|
|
146
|
+
if content:
|
|
147
|
+
parts = getattr(content, "parts", None)
|
|
148
|
+
if parts:
|
|
149
|
+
for part in parts:
|
|
150
|
+
fc = getattr(part, "function_call", None)
|
|
151
|
+
if fc:
|
|
152
|
+
name = getattr(fc, "name", None)
|
|
153
|
+
args = getattr(fc, "args", {}) or {}
|
|
154
|
+
calls.append((name, args))
|
|
155
|
+
else:
|
|
156
|
+
if isinstance(resp, dict):
|
|
157
|
+
content = resp.get("content", {})
|
|
158
|
+
parts = content.get("parts", [])
|
|
159
|
+
for part in parts:
|
|
160
|
+
if "function_call" in part:
|
|
161
|
+
fc = part["function_call"]
|
|
162
|
+
calls.append((fc.get("name"), fc.get("args", {})))
|
|
163
|
+
except Exception as e:
|
|
164
|
+
print(f"Gemini: failed to parse function_call: {e}")
|
|
165
|
+
return calls
|
|
166
|
+
|
|
167
|
+
def _pass_action(self, action) -> Tuple[Optional[str], dict]:
|
|
168
|
+
"""
|
|
169
|
+
Convert old-style action object into a direct function call name + args,
|
|
170
|
+
without changing the semantic names (workers handle details).
|
|
171
|
+
"""
|
|
172
|
+
try:
|
|
173
|
+
atype = getattr(action, "type", None)
|
|
174
|
+
if not atype:
|
|
175
|
+
return None, {}
|
|
176
|
+
atype = str(atype)
|
|
177
|
+
|
|
178
|
+
# Build args by introspection; workers know how to interpret them
|
|
179
|
+
args = {}
|
|
180
|
+
for attr in ("x", "y", "button", "scroll_x", "scroll_y", "keys", "text", "path"):
|
|
181
|
+
if hasattr(action, attr):
|
|
182
|
+
args[attr] = getattr(action, attr)
|
|
183
|
+
|
|
184
|
+
if atype == "double_click":
|
|
185
|
+
args["num_clicks"] = 2
|
|
186
|
+
|
|
187
|
+
return atype, args
|
|
188
|
+
except Exception as e:
|
|
189
|
+
print(f"Gemini: pass_action error: {e}")
|
|
190
|
+
return None, {}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date:
|
|
9
|
+
# Updated Date: 2026.01.02 19:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import json
|
|
@@ -97,7 +97,7 @@ class Realtime:
|
|
|
97
97
|
|
|
98
98
|
# Tools
|
|
99
99
|
tools = self.window.core.api.google.tools.prepare(model, context.external_functions)
|
|
100
|
-
remote_tools = self.window.core.api.google.build_remote_tools(model)
|
|
100
|
+
remote_tools = self.window.core.api.google.remote_tools.build_remote_tools(model)
|
|
101
101
|
if tools:
|
|
102
102
|
remote_tools = [] # in Google, remote tools are not allowed if function calling is used
|
|
103
103
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# ================================================== #
|
|
4
|
+
# This file is a part of PYGPT package #
|
|
5
|
+
# Website: https://pygpt.net #
|
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
|
+
# MIT License #
|
|
8
|
+
# Created By : Marcin Szczygliński #
|
|
9
|
+
# Updated Date: 2026.01.02 19:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
from google.genai import types as gtypes
|
|
13
|
+
|
|
14
|
+
from pygpt_net.item.model import ModelItem
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RemoteTools:
|
|
18
|
+
def __init__(self, window=None):
|
|
19
|
+
"""
|
|
20
|
+
Remote Tools helpers for Google GenAI.
|
|
21
|
+
|
|
22
|
+
:param window: Window instance
|
|
23
|
+
"""
|
|
24
|
+
self.window = window
|
|
25
|
+
|
|
26
|
+
def build_remote_tools(self, model: ModelItem = None) -> list:
|
|
27
|
+
"""
|
|
28
|
+
Build Google GenAI remote tools based on config flags.
|
|
29
|
+
- remote_tools.google.web_search: enables grounding via Google Search (Gemini 2.x)
|
|
30
|
+
or GoogleSearchRetrieval (Gemini 1.5 fallback).
|
|
31
|
+
- remote_tools.google.code_interpreter: enables code execution tool.
|
|
32
|
+
|
|
33
|
+
Returns a list of gtypes.Tool objects (can be empty).
|
|
34
|
+
|
|
35
|
+
:param model: ModelItem
|
|
36
|
+
:return: list of gtypes.Tool
|
|
37
|
+
"""
|
|
38
|
+
tools: list = []
|
|
39
|
+
cfg = self.window.core.config
|
|
40
|
+
model_id = (model.id if model and getattr(model, "id", None) else "").lower()
|
|
41
|
+
is_web = self.window.controller.chat.remote_tools.enabled(model, "web_search") # get global config
|
|
42
|
+
|
|
43
|
+
# Google Search tool
|
|
44
|
+
if is_web and "image" not in model.id:
|
|
45
|
+
try:
|
|
46
|
+
if not model_id.startswith("gemini-1.5") and not model_id.startswith("models/gemini-1.5"):
|
|
47
|
+
# Gemini 2.x uses GoogleSearch
|
|
48
|
+
tools.append(gtypes.Tool(google_search=gtypes.GoogleSearch()))
|
|
49
|
+
else:
|
|
50
|
+
# Gemini 1.5 fallback uses GoogleSearchRetrieval
|
|
51
|
+
# Note: Supported only for 1.5 models.
|
|
52
|
+
tools.append(gtypes.Tool(
|
|
53
|
+
google_search_retrieval=gtypes.GoogleSearchRetrieval()
|
|
54
|
+
))
|
|
55
|
+
except Exception as e:
|
|
56
|
+
# Do not break the request if tool construction fails
|
|
57
|
+
self.window.core.debug.log(e)
|
|
58
|
+
|
|
59
|
+
# Code Execution tool
|
|
60
|
+
if cfg.get("remote_tools.google.code_interpreter") and "image" not in model.id:
|
|
61
|
+
try:
|
|
62
|
+
tools.append(gtypes.Tool(code_execution=gtypes.ToolCodeExecution))
|
|
63
|
+
except Exception as e:
|
|
64
|
+
self.window.core.debug.log(e)
|
|
65
|
+
|
|
66
|
+
# URL Context tool
|
|
67
|
+
if cfg.get("remote_tools.google.url_ctx") and "image" not in model.id:
|
|
68
|
+
try:
|
|
69
|
+
# Supported on Gemini 2.x+ models (not on 1.5)
|
|
70
|
+
if not model_id.startswith("gemini-1.5") and not model_id.startswith("models/gemini-1.5"):
|
|
71
|
+
tools.append(gtypes.Tool(url_context=gtypes.UrlContext))
|
|
72
|
+
except Exception as e:
|
|
73
|
+
self.window.core.debug.log(e)
|
|
74
|
+
|
|
75
|
+
# Google Maps
|
|
76
|
+
if cfg.get("remote_tools.google.maps") and "image" not in model.id:
|
|
77
|
+
try:
|
|
78
|
+
tools.append(gtypes.Tool(google_maps=gtypes.GoogleMaps()))
|
|
79
|
+
except Exception as e:
|
|
80
|
+
self.window.core.debug.log(e)
|
|
81
|
+
|
|
82
|
+
# File search
|
|
83
|
+
if cfg.get("remote_tools.google.file_search") and "image" not in model.id:
|
|
84
|
+
store_ids = cfg.get("remote_tools.google.file_search.args", "")
|
|
85
|
+
file_search_store_names = [s.strip() for s in store_ids.split(",") if s.strip()]
|
|
86
|
+
try:
|
|
87
|
+
tools.append(gtypes.Tool(file_search=gtypes.FileSearch(
|
|
88
|
+
file_search_store_names=file_search_store_names,
|
|
89
|
+
)))
|
|
90
|
+
except Exception as e:
|
|
91
|
+
self.window.core.debug.log(e)
|
|
92
|
+
|
|
93
|
+
return tools
|