pygpt-net 2.6.59__py3-none-any.whl → 2.6.60__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 +4 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +9 -5
- pygpt_net/controller/__init__.py +1 -0
- pygpt_net/controller/presets/editor.py +442 -39
- pygpt_net/core/agents/custom/__init__.py +275 -0
- pygpt_net/core/agents/custom/debug.py +64 -0
- pygpt_net/core/agents/custom/factory.py +109 -0
- pygpt_net/core/agents/custom/graph.py +71 -0
- pygpt_net/core/agents/custom/llama_index/__init__.py +10 -0
- pygpt_net/core/agents/custom/llama_index/factory.py +89 -0
- pygpt_net/core/agents/custom/llama_index/router_streamer.py +106 -0
- pygpt_net/core/agents/custom/llama_index/runner.py +529 -0
- pygpt_net/core/agents/custom/llama_index/stream.py +56 -0
- pygpt_net/core/agents/custom/llama_index/utils.py +242 -0
- pygpt_net/core/agents/custom/logging.py +50 -0
- pygpt_net/core/agents/custom/memory.py +51 -0
- pygpt_net/core/agents/custom/router.py +116 -0
- pygpt_net/core/agents/custom/router_streamer.py +187 -0
- pygpt_net/core/agents/custom/runner.py +454 -0
- pygpt_net/core/agents/custom/schema.py +125 -0
- pygpt_net/core/agents/custom/utils.py +181 -0
- pygpt_net/core/agents/provider.py +72 -7
- pygpt_net/core/agents/runner.py +7 -4
- pygpt_net/core/agents/runners/helpers.py +1 -1
- pygpt_net/core/agents/runners/llama_workflow.py +3 -0
- pygpt_net/core/agents/runners/openai_workflow.py +8 -1
- pygpt_net/{ui/widget/builder → core/node_editor}/__init__.py +2 -2
- pygpt_net/core/{builder → node_editor}/graph.py +11 -218
- pygpt_net/core/node_editor/models.py +111 -0
- pygpt_net/core/node_editor/types.py +76 -0
- pygpt_net/core/node_editor/utils.py +17 -0
- pygpt_net/core/render/web/renderer.py +10 -8
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/locale/locale.en.ini +4 -4
- pygpt_net/item/agent.py +5 -1
- pygpt_net/item/preset.py +19 -1
- pygpt_net/provider/agents/base.py +33 -2
- pygpt_net/provider/agents/llama_index/flow_from_schema.py +92 -0
- pygpt_net/provider/agents/openai/flow_from_schema.py +96 -0
- pygpt_net/provider/core/agent/json_file.py +11 -5
- pygpt_net/tools/agent_builder/tool.py +217 -52
- pygpt_net/tools/agent_builder/ui/dialogs.py +119 -24
- pygpt_net/tools/agent_builder/ui/list.py +37 -10
- pygpt_net/ui/dialog/preset.py +16 -1
- pygpt_net/ui/main.py +1 -1
- pygpt_net/{core/builder → ui/widget/node_editor}/__init__.py +2 -2
- pygpt_net/ui/widget/node_editor/command.py +373 -0
- pygpt_net/ui/widget/node_editor/editor.py +2038 -0
- pygpt_net/ui/widget/node_editor/item.py +492 -0
- pygpt_net/ui/widget/node_editor/node.py +1205 -0
- pygpt_net/ui/widget/node_editor/utils.py +17 -0
- pygpt_net/ui/widget/node_editor/view.py +247 -0
- {pygpt_net-2.6.59.dist-info → pygpt_net-2.6.60.dist-info}/METADATA +72 -2
- {pygpt_net-2.6.59.dist-info → pygpt_net-2.6.60.dist-info}/RECORD +59 -33
- pygpt_net/core/agents/custom.py +0 -150
- pygpt_net/ui/widget/builder/editor.py +0 -2001
- {pygpt_net-2.6.59.dist-info → pygpt_net-2.6.60.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.59.dist-info → pygpt_net-2.6.60.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.59.dist-info → pygpt_net-2.6.60.dist-info}/entry_points.txt +0 -0
|
@@ -6,229 +6,18 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date: 2025.09.
|
|
9
|
+
# Updated Date: 2025.09.24 00:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
from typing import Dict, List, Optional, Tuple, Any
|
|
14
|
-
from dataclasses import dataclass, field
|
|
15
|
-
from uuid import uuid4
|
|
16
|
-
from PySide6.QtCore import QObject, Signal
|
|
17
14
|
import re
|
|
18
15
|
|
|
16
|
+
from PySide6.QtCore import QObject, Signal
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# ------------------------ Data models (pure data) ------------------------
|
|
25
|
-
|
|
26
|
-
@dataclass
|
|
27
|
-
class PropertyModel:
|
|
28
|
-
uuid: str
|
|
29
|
-
id: str
|
|
30
|
-
type: str # "slot", "str", "int", "float", "bool", "combo", "text"
|
|
31
|
-
name: str
|
|
32
|
-
editable: bool = True
|
|
33
|
-
value: Any = None
|
|
34
|
-
allowed_inputs: int = 0 # 0 none, -1 unlimited, >0 limit
|
|
35
|
-
allowed_outputs: int = 0 # 0 none, -1 unlimited, >0 limit
|
|
36
|
-
options: Optional[List[str]] = None # for combo
|
|
37
|
-
|
|
38
|
-
def to_dict(self) -> dict:
|
|
39
|
-
return {
|
|
40
|
-
"uuid": self.uuid,
|
|
41
|
-
"id": self.id,
|
|
42
|
-
"type": self.type,
|
|
43
|
-
"name": self.name,
|
|
44
|
-
"editable": self.editable,
|
|
45
|
-
"value": self.value,
|
|
46
|
-
"allowed_inputs": self.allowed_inputs,
|
|
47
|
-
"allowed_outputs": self.allowed_outputs,
|
|
48
|
-
"options": self.options or [],
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@staticmethod
|
|
52
|
-
def from_dict(d: dict) -> "PropertyModel":
|
|
53
|
-
return PropertyModel(
|
|
54
|
-
uuid=d.get("uuid", gen_uuid()),
|
|
55
|
-
id=d["id"],
|
|
56
|
-
type=d["type"],
|
|
57
|
-
name=d.get("name", d["id"]),
|
|
58
|
-
editable=d.get("editable", True),
|
|
59
|
-
value=d.get("value"),
|
|
60
|
-
allowed_inputs=d.get("allowed_inputs", 0),
|
|
61
|
-
allowed_outputs=d.get("allowed_outputs", 0),
|
|
62
|
-
options=d.get("options") or None,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
@dataclass
|
|
67
|
-
class NodeModel:
|
|
68
|
-
uuid: str
|
|
69
|
-
id: str
|
|
70
|
-
name: str
|
|
71
|
-
type: str
|
|
72
|
-
properties: Dict[str, PropertyModel] = field(default_factory=dict)
|
|
73
|
-
|
|
74
|
-
def to_dict(self) -> dict:
|
|
75
|
-
return {
|
|
76
|
-
"uuid": self.uuid,
|
|
77
|
-
"id": self.id,
|
|
78
|
-
"name": self.name,
|
|
79
|
-
"type": self.type,
|
|
80
|
-
"properties": {pid: p.to_dict() for pid, p in self.properties.items()},
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
@staticmethod
|
|
84
|
-
def from_dict(d: dict) -> "NodeModel":
|
|
85
|
-
props = {pid: PropertyModel.from_dict(pd) for pid, pd in d.get("properties", {}).items()}
|
|
86
|
-
return NodeModel(
|
|
87
|
-
uuid=d.get("uuid", gen_uuid()),
|
|
88
|
-
id=d["id"],
|
|
89
|
-
name=d.get("name", d["id"]),
|
|
90
|
-
type=d["type"],
|
|
91
|
-
properties=props,
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
@dataclass
|
|
96
|
-
class ConnectionModel:
|
|
97
|
-
uuid: str
|
|
98
|
-
src_node: str
|
|
99
|
-
src_prop: str
|
|
100
|
-
dst_node: str
|
|
101
|
-
dst_prop: str
|
|
102
|
-
|
|
103
|
-
def to_dict(self) -> dict:
|
|
104
|
-
return {
|
|
105
|
-
"uuid": self.uuid,
|
|
106
|
-
"src_node": self.src_node, "src_prop": self.src_prop,
|
|
107
|
-
"dst_node": self.dst_node, "dst_prop": self.dst_prop,
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
@staticmethod
|
|
111
|
-
def from_dict(d: dict) -> "ConnectionModel":
|
|
112
|
-
return ConnectionModel(
|
|
113
|
-
uuid=d.get("uuid", gen_uuid()),
|
|
114
|
-
src_node=d["src_node"], src_prop=d["src_prop"],
|
|
115
|
-
dst_node=d["dst_node"], dst_prop=d["dst_prop"],
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# ------------------------ Types registry (templates) ------------------------
|
|
120
|
-
|
|
121
|
-
@dataclass
|
|
122
|
-
class PropertySpec:
|
|
123
|
-
id: str
|
|
124
|
-
type: str
|
|
125
|
-
name: Optional[str] = None
|
|
126
|
-
editable: bool = True
|
|
127
|
-
value: Any = None
|
|
128
|
-
allowed_inputs: int = 0
|
|
129
|
-
allowed_outputs: int = 0
|
|
130
|
-
options: Optional[List[str]] = None
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
@dataclass
|
|
134
|
-
class NodeTypeSpec:
|
|
135
|
-
type_name: str
|
|
136
|
-
title: Optional[str] = None
|
|
137
|
-
properties: List[PropertySpec] = field(default_factory=list)
|
|
138
|
-
# Below are optional extensions for agent-flow needs:
|
|
139
|
-
base_id: Optional[str] = None # base prefix for friendly ids, e.g. "agent"
|
|
140
|
-
export_kind: Optional[str] = None # short kind for export, e.g. "agent", "start"
|
|
141
|
-
bg_color: Optional[str] = None # optional per-type background color (CSS/hex)
|
|
142
|
-
|
|
143
|
-
class NodeTypeRegistry:
|
|
144
|
-
"""Registry for node type specifications. Extend/override in subclasses."""
|
|
145
|
-
def __init__(self):
|
|
146
|
-
self._types: Dict[str, NodeTypeSpec] = {}
|
|
147
|
-
self._install_default_types()
|
|
148
|
-
|
|
149
|
-
def register(self, spec: NodeTypeSpec):
|
|
150
|
-
self._types[spec.type_name] = spec
|
|
151
|
-
|
|
152
|
-
def types(self) -> List[str]:
|
|
153
|
-
return list(self._types.keys())
|
|
154
|
-
|
|
155
|
-
def get(self, type_name: str) -> Optional[NodeTypeSpec]:
|
|
156
|
-
return self._types.get(type_name)
|
|
157
|
-
|
|
158
|
-
def _install_default_types(self):
|
|
159
|
-
# Example/basic nodes kept intact
|
|
160
|
-
self.register(NodeTypeSpec(
|
|
161
|
-
type_name="Value/Float",
|
|
162
|
-
title="Float",
|
|
163
|
-
properties=[
|
|
164
|
-
PropertySpec(id="value", type="float", name="Value", editable=True, value=0.0,
|
|
165
|
-
allowed_inputs=0, allowed_outputs=1),
|
|
166
|
-
]
|
|
167
|
-
))
|
|
168
|
-
self.register(NodeTypeSpec(
|
|
169
|
-
type_name="Math/Add",
|
|
170
|
-
title="Add",
|
|
171
|
-
properties=[
|
|
172
|
-
PropertySpec(id="A", type="float", name="A", editable=True, value=0.0, allowed_inputs=1, allowed_outputs=0),
|
|
173
|
-
PropertySpec(id="B", type="float", name="B", editable=True, value=0.0, allowed_inputs=1, allowed_outputs=0),
|
|
174
|
-
PropertySpec(id="result", type="float", name="Result", editable=False, value=None, allowed_inputs=0, allowed_outputs=1),
|
|
175
|
-
]
|
|
176
|
-
))
|
|
177
|
-
# Tip: to allow multiple connections to an input or output, set allowed_inputs/allowed_outputs to -1.
|
|
178
|
-
|
|
179
|
-
# Agent-flow nodes
|
|
180
|
-
# Start
|
|
181
|
-
self.register(NodeTypeSpec(
|
|
182
|
-
type_name="Flow/Start",
|
|
183
|
-
title="Start",
|
|
184
|
-
base_id="start",
|
|
185
|
-
export_kind="start",
|
|
186
|
-
bg_color="#2D5A27",
|
|
187
|
-
properties=[
|
|
188
|
-
PropertySpec(id="output", type="flow", name="Output", editable=False, allowed_inputs=0, allowed_outputs=1),
|
|
189
|
-
# base_id will be auto-injected as read-only property at creation
|
|
190
|
-
],
|
|
191
|
-
))
|
|
192
|
-
# Agent
|
|
193
|
-
self.register(NodeTypeSpec(
|
|
194
|
-
type_name="Flow/Agent",
|
|
195
|
-
title="Agent",
|
|
196
|
-
base_id="agent",
|
|
197
|
-
export_kind="agent",
|
|
198
|
-
bg_color="#304A6E",
|
|
199
|
-
properties=[
|
|
200
|
-
PropertySpec(id="name", type="str", name="Name", editable=True, value=""),
|
|
201
|
-
PropertySpec(id="instruction", type="text", name="Instruction", editable=True, value=""),
|
|
202
|
-
PropertySpec(id="remote_tools", type="bool", name="Remote tools", editable=True, value=True),
|
|
203
|
-
PropertySpec(id="local_tools", type="bool", name="Local tools", editable=True, value=True),
|
|
204
|
-
PropertySpec(id="input", type="flow", name="Input", editable=False, allowed_inputs=-1, allowed_outputs=0),
|
|
205
|
-
PropertySpec(id="output", type="flow", name="Output", editable=False, allowed_inputs=0, allowed_outputs=1),
|
|
206
|
-
PropertySpec(id="memory", type="memory", name="Memory", editable=False, allowed_inputs=0, allowed_outputs=1),
|
|
207
|
-
],
|
|
208
|
-
))
|
|
209
|
-
# Memory
|
|
210
|
-
self.register(NodeTypeSpec(
|
|
211
|
-
type_name="Flow/Memory",
|
|
212
|
-
title="Memory",
|
|
213
|
-
base_id="mem",
|
|
214
|
-
export_kind="memory",
|
|
215
|
-
bg_color="#593E78",
|
|
216
|
-
properties=[
|
|
217
|
-
PropertySpec(id="name", type="str", name="Name", editable=True, value=""),
|
|
218
|
-
PropertySpec(id="input", type="memory", name="Input", editable=False, allowed_inputs=-1, allowed_outputs=0),
|
|
219
|
-
],
|
|
220
|
-
))
|
|
221
|
-
# End
|
|
222
|
-
self.register(NodeTypeSpec(
|
|
223
|
-
type_name="Flow/End",
|
|
224
|
-
title="End",
|
|
225
|
-
base_id="end",
|
|
226
|
-
export_kind="end",
|
|
227
|
-
bg_color="#6B2E2E",
|
|
228
|
-
properties=[
|
|
229
|
-
PropertySpec(id="input", type="flow", name="Input", editable=False, allowed_inputs=1, allowed_outputs=0),
|
|
230
|
-
],
|
|
231
|
-
))
|
|
18
|
+
from .models import NodeModel, ConnectionModel, PropertyModel
|
|
19
|
+
from .types import NodeTypeRegistry
|
|
20
|
+
from .utils import gen_uuid
|
|
232
21
|
|
|
233
22
|
|
|
234
23
|
# ------------------------ Graph (Qt QObject + signals) ------------------------
|
|
@@ -412,8 +201,8 @@ class NodeGraph(QObject):
|
|
|
412
201
|
for c in self.connections.values()]
|
|
413
202
|
return {"nodes": nodes_out, "connections": conns_out}
|
|
414
203
|
|
|
415
|
-
# --- Export to
|
|
416
|
-
def
|
|
204
|
+
# --- Export to list schema (list of nodes with slots/in-out) ---
|
|
205
|
+
def to_list_schema(self) -> List[dict]:
|
|
417
206
|
# Build helper maps
|
|
418
207
|
uuid_to_node: Dict[str, NodeModel] = dict(self.nodes)
|
|
419
208
|
uuid_to_id: Dict[str, str] = {u: n.id for u, n in uuid_to_node.items()}
|
|
@@ -474,5 +263,9 @@ class NodeGraph(QObject):
|
|
|
474
263
|
def clear(self, silent: bool = False):
|
|
475
264
|
self.nodes.clear()
|
|
476
265
|
self.connections.clear()
|
|
266
|
+
# Reset counters to keep friendly IDs strictly per-layout.
|
|
267
|
+
# After a clear, numbering starts again from 1 for each base prefix.
|
|
268
|
+
self._node_counter = 1
|
|
269
|
+
self._id_counters.clear()
|
|
477
270
|
if not silent:
|
|
478
271
|
self.cleared.emit()
|
|
@@ -0,0 +1,111 @@
|
|
|
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: 2025.09.24 00:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
from typing import Dict, List, Optional, Any
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
|
|
16
|
+
from .utils import gen_uuid
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ------------------------ Data models (pure data) ------------------------
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class PropertyModel:
|
|
23
|
+
uuid: str
|
|
24
|
+
id: str
|
|
25
|
+
type: str # "slot", "str", "int", "float", "bool", "combo", "text"
|
|
26
|
+
name: str
|
|
27
|
+
editable: bool = True
|
|
28
|
+
value: Any = None
|
|
29
|
+
allowed_inputs: int = 0 # 0 none, -1 unlimited, >0 limit
|
|
30
|
+
allowed_outputs: int = 0 # 0 none, -1 unlimited, >0 limit
|
|
31
|
+
options: Optional[List[str]] = None # for combo
|
|
32
|
+
|
|
33
|
+
def to_dict(self) -> dict:
|
|
34
|
+
return {
|
|
35
|
+
"uuid": self.uuid,
|
|
36
|
+
"id": self.id,
|
|
37
|
+
"type": self.type,
|
|
38
|
+
"name": self.name,
|
|
39
|
+
"editable": self.editable,
|
|
40
|
+
"value": self.value,
|
|
41
|
+
"allowed_inputs": self.allowed_inputs,
|
|
42
|
+
"allowed_outputs": self.allowed_outputs,
|
|
43
|
+
"options": self.options or [],
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def from_dict(d: dict) -> "PropertyModel":
|
|
48
|
+
return PropertyModel(
|
|
49
|
+
uuid=d.get("uuid", gen_uuid()),
|
|
50
|
+
id=d["id"],
|
|
51
|
+
type=d["type"],
|
|
52
|
+
name=d.get("name", d["id"]),
|
|
53
|
+
editable=d.get("editable", True),
|
|
54
|
+
value=d.get("value"),
|
|
55
|
+
allowed_inputs=d.get("allowed_inputs", 0),
|
|
56
|
+
allowed_outputs=d.get("allowed_outputs", 0),
|
|
57
|
+
options=d.get("options") or None,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class NodeModel:
|
|
63
|
+
uuid: str
|
|
64
|
+
id: str
|
|
65
|
+
name: str
|
|
66
|
+
type: str
|
|
67
|
+
properties: Dict[str, PropertyModel] = field(default_factory=dict)
|
|
68
|
+
|
|
69
|
+
def to_dict(self) -> dict:
|
|
70
|
+
return {
|
|
71
|
+
"uuid": self.uuid,
|
|
72
|
+
"id": self.id,
|
|
73
|
+
"name": self.name,
|
|
74
|
+
"type": self.type,
|
|
75
|
+
"properties": {pid: p.to_dict() for pid, p in self.properties.items()},
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def from_dict(d: dict) -> "NodeModel":
|
|
80
|
+
props = {pid: PropertyModel.from_dict(pd) for pid, pd in d.get("properties", {}).items()}
|
|
81
|
+
return NodeModel(
|
|
82
|
+
uuid=d.get("uuid", gen_uuid()),
|
|
83
|
+
id=d["id"],
|
|
84
|
+
name=d.get("name", d["id"]),
|
|
85
|
+
type=d["type"],
|
|
86
|
+
properties=props,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass
|
|
91
|
+
class ConnectionModel:
|
|
92
|
+
uuid: str
|
|
93
|
+
src_node: str
|
|
94
|
+
src_prop: str
|
|
95
|
+
dst_node: str
|
|
96
|
+
dst_prop: str
|
|
97
|
+
|
|
98
|
+
def to_dict(self) -> dict:
|
|
99
|
+
return {
|
|
100
|
+
"uuid": self.uuid,
|
|
101
|
+
"src_node": self.src_node, "src_prop": self.src_prop,
|
|
102
|
+
"dst_node": self.dst_node, "dst_prop": self.dst_prop,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def from_dict(d: dict) -> "ConnectionModel":
|
|
107
|
+
return ConnectionModel(
|
|
108
|
+
uuid=d.get("uuid", gen_uuid()),
|
|
109
|
+
src_node=d["src_node"], src_prop=d["src_prop"],
|
|
110
|
+
dst_node=d["dst_node"], dst_prop=d["dst_prop"],
|
|
111
|
+
)
|
|
@@ -0,0 +1,76 @@
|
|
|
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: 2025.09.24 00:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
from typing import Dict, List, Optional, Any
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# ------------------------ Types registry (templates) ------------------------
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class PropertySpec:
|
|
21
|
+
id: str
|
|
22
|
+
type: str
|
|
23
|
+
name: Optional[str] = None
|
|
24
|
+
editable: bool = True
|
|
25
|
+
value: Any = None
|
|
26
|
+
allowed_inputs: int = 0
|
|
27
|
+
allowed_outputs: int = 0
|
|
28
|
+
options: Optional[List[str]] = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class NodeTypeSpec:
|
|
33
|
+
type_name: str
|
|
34
|
+
title: Optional[str] = None
|
|
35
|
+
properties: List[PropertySpec] = field(default_factory=list)
|
|
36
|
+
# Below are optional extensions for agent-flow needs:
|
|
37
|
+
base_id: Optional[str] = None # base prefix for friendly ids, e.g. "agent"
|
|
38
|
+
export_kind: Optional[str] = None # short kind for export, e.g. "agent", "start"
|
|
39
|
+
bg_color: Optional[str] = None # optional per-type background color (CSS/hex)
|
|
40
|
+
|
|
41
|
+
class NodeTypeRegistry:
|
|
42
|
+
"""Registry for node type specifications. Extend/override in subclasses."""
|
|
43
|
+
def __init__(self, empty: bool = False):
|
|
44
|
+
self._types: Dict[str, NodeTypeSpec] = {}
|
|
45
|
+
if not empty:
|
|
46
|
+
self._install_default_types()
|
|
47
|
+
|
|
48
|
+
def register(self, spec: NodeTypeSpec):
|
|
49
|
+
self._types[spec.type_name] = spec
|
|
50
|
+
|
|
51
|
+
def types(self) -> List[str]:
|
|
52
|
+
return list(self._types.keys())
|
|
53
|
+
|
|
54
|
+
def get(self, type_name: str) -> Optional[NodeTypeSpec]:
|
|
55
|
+
return self._types.get(type_name)
|
|
56
|
+
|
|
57
|
+
def _install_default_types(self):
|
|
58
|
+
# Example/basic nodes kept intact
|
|
59
|
+
self.register(NodeTypeSpec(
|
|
60
|
+
type_name="Value/Float",
|
|
61
|
+
title="Float",
|
|
62
|
+
properties=[
|
|
63
|
+
PropertySpec(id="value", type="float", name="Value", editable=True, value=0.0,
|
|
64
|
+
allowed_inputs=0, allowed_outputs=1),
|
|
65
|
+
]
|
|
66
|
+
))
|
|
67
|
+
self.register(NodeTypeSpec(
|
|
68
|
+
type_name="Math/Add",
|
|
69
|
+
title="Add",
|
|
70
|
+
properties=[
|
|
71
|
+
PropertySpec(id="A", type="float", name="A", editable=True, value=0.0, allowed_inputs=1, allowed_outputs=0),
|
|
72
|
+
PropertySpec(id="B", type="float", name="B", editable=True, value=0.0, allowed_inputs=1, allowed_outputs=0),
|
|
73
|
+
PropertySpec(id="result", type="float", name="Result", editable=False, value=None, allowed_inputs=0, allowed_outputs=1),
|
|
74
|
+
]
|
|
75
|
+
))
|
|
76
|
+
# Tip: to allow multiple connections to an input or output, set allowed_inputs/allowed_outputs to -1.
|
|
@@ -0,0 +1,17 @@
|
|
|
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: 2025.09.24 00:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
from uuid import uuid4
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def gen_uuid() -> str:
|
|
17
|
+
return str(uuid4())
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
# Updated Date: 2025.09.17 05:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
-
import gc
|
|
13
12
|
import json
|
|
14
13
|
import os
|
|
15
14
|
import re
|
|
@@ -21,7 +20,7 @@ from typing import Optional, List, Any, Dict, Tuple
|
|
|
21
20
|
from time import monotonic
|
|
22
21
|
from io import StringIO
|
|
23
22
|
|
|
24
|
-
from PySide6.QtCore import QTimer, QUrl
|
|
23
|
+
from PySide6.QtCore import QTimer, QUrl, QCoreApplication, QEventLoop, QEvent
|
|
25
24
|
from PySide6.QtWebEngineCore import QWebEnginePage
|
|
26
25
|
|
|
27
26
|
from pygpt_net.core.render.base import BaseRenderer
|
|
@@ -496,9 +495,10 @@ class Renderer(BaseRenderer):
|
|
|
496
495
|
|
|
497
496
|
Soft cleanup, called after each context is done.
|
|
498
497
|
"""
|
|
499
|
-
|
|
500
|
-
gc.collect()
|
|
498
|
+
def cleanup():
|
|
501
499
|
malloc_trim_linux()
|
|
500
|
+
try:
|
|
501
|
+
QTimer.singleShot(0, cleanup)
|
|
502
502
|
except Exception:
|
|
503
503
|
pass
|
|
504
504
|
|
|
@@ -1300,6 +1300,12 @@ class Renderer(BaseRenderer):
|
|
|
1300
1300
|
tab.unwrap(node)
|
|
1301
1301
|
self.window.ui.nodes['output'].pop(tab.pid, None)
|
|
1302
1302
|
|
|
1303
|
+
try:
|
|
1304
|
+
QCoreApplication.sendPostedEvents(None, QEvent.DeferredDelete)
|
|
1305
|
+
QCoreApplication.processEvents(QEventLoop.AllEvents, 0)
|
|
1306
|
+
except Exception:
|
|
1307
|
+
pass
|
|
1308
|
+
|
|
1303
1309
|
view = ChatWebOutput(self.window)
|
|
1304
1310
|
view.set_tab(tab)
|
|
1305
1311
|
view.set_meta(meta)
|
|
@@ -1310,10 +1316,6 @@ class Renderer(BaseRenderer):
|
|
|
1310
1316
|
tab.add_ref(view)
|
|
1311
1317
|
view.setVisible(True)
|
|
1312
1318
|
self.window.ui.nodes['output'][tab.pid] = view
|
|
1313
|
-
try:
|
|
1314
|
-
gc.collect()
|
|
1315
|
-
except Exception:
|
|
1316
|
-
pass
|
|
1317
1319
|
self.auto_cleanup_soft(meta)
|
|
1318
1320
|
|
|
1319
1321
|
def get_output_node(self, meta: Optional[CtxMeta] = None) -> Optional[ChatWebOutput]:
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"__meta__": {
|
|
3
|
-
"version": "2.6.
|
|
4
|
-
"app.version": "2.6.
|
|
5
|
-
"updated_at": "2025-09-
|
|
3
|
+
"version": "2.6.60",
|
|
4
|
+
"app.version": "2.6.60",
|
|
5
|
+
"updated_at": "2025-09-25T00:00:00"
|
|
6
6
|
},
|
|
7
7
|
"access.audio.event.speech": false,
|
|
8
8
|
"access.audio.event.speech.disabled": [],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"__meta__": {
|
|
3
|
-
"version": "2.6.
|
|
4
|
-
"app.version": "2.6.
|
|
5
|
-
"updated_at": "2025-09-
|
|
3
|
+
"version": "2.6.60",
|
|
4
|
+
"app.version": "2.6.60",
|
|
5
|
+
"updated_at": "2025-09-25T00:00:00"
|
|
6
6
|
},
|
|
7
7
|
"items": {
|
|
8
8
|
"SpeakLeash/bielik-11b-v2.3-instruct:Q4_K_M": {
|
|
@@ -75,7 +75,7 @@ action.video.transcribe = Transcribe audio...
|
|
|
75
75
|
agent.builder.confirm.clear.msg = Do you really want to clear the graph?
|
|
76
76
|
agent.builder.confirm.clear.title = Clear
|
|
77
77
|
agent.builder.confirm.delete.msg = Do you really want to delete the agent?
|
|
78
|
-
agent.builder.title =
|
|
78
|
+
agent.builder.title = Agents Builder (beta)
|
|
79
79
|
agent.coder.additional.label = Additional prompt
|
|
80
80
|
agent.coder.additional.prompt.desc = Additional prompt for agent (will be added to the base prompt)
|
|
81
81
|
agent.coder.base.label = Base prompt
|
|
@@ -115,7 +115,7 @@ agent.option.section.worker = Worker
|
|
|
115
115
|
agent.option.section.writer = Writer
|
|
116
116
|
agent.option.tools.local = Allow local tools
|
|
117
117
|
agent.option.tools.local.desc = Allow usage of local tools for this agent
|
|
118
|
-
agent.option.tools.remote =
|
|
118
|
+
agent.option.tools.remote = Allow remote tools
|
|
119
119
|
agent.option.tools.remote.desc = Allow usage of remote tools for this agent
|
|
120
120
|
agent.planner.plan.label = Planner (initial)
|
|
121
121
|
agent.planner.plan.prompt.desc = Initial plan prompt
|
|
@@ -780,7 +780,7 @@ menu.config.save = Save config
|
|
|
780
780
|
menu.config.settings = Settings...
|
|
781
781
|
menu.debug = Debug
|
|
782
782
|
menu.debug.agent = Agent...
|
|
783
|
-
menu.debug.agent_builder =
|
|
783
|
+
menu.debug.agent_builder = Agents Builder (beta)
|
|
784
784
|
menu.debug.app.log = View log file (app.log)
|
|
785
785
|
menu.debug.assistants = Assistants...
|
|
786
786
|
menu.debug.attachments = Files / attachments...
|
|
@@ -835,7 +835,7 @@ menu.theme.style = Style...
|
|
|
835
835
|
menu.theme.syntax = Code syntax highlight...
|
|
836
836
|
menu.theme.tooltips = Show tooltips
|
|
837
837
|
menu.tools = Tools
|
|
838
|
-
menu.tools.agent.builder =
|
|
838
|
+
menu.tools.agent.builder = Agents Builder (beta)
|
|
839
839
|
menu.tools.audio.transcribe = Transcribe Audio/Video Files
|
|
840
840
|
menu.tools.html_canvas = HTML/JS Canvas
|
|
841
841
|
menu.tools.image.viewer = Image Viewer
|
pygpt_net/item/agent.py
CHANGED
|
@@ -20,18 +20,21 @@ class AgentItem:
|
|
|
20
20
|
id: Optional[object] = None
|
|
21
21
|
name: Optional[object] = None
|
|
22
22
|
layout: dict = field(default_factory=dict)
|
|
23
|
+
schema: list = field(default_factory=list)
|
|
23
24
|
|
|
24
25
|
def __init__(self):
|
|
25
26
|
"""Custom agent item"""
|
|
26
27
|
self.id = None
|
|
27
28
|
self.name = None
|
|
28
29
|
self.layout = {}
|
|
30
|
+
self.schema = []
|
|
29
31
|
|
|
30
32
|
def reset(self):
|
|
31
33
|
"""Reset"""
|
|
32
34
|
self.id = None
|
|
33
35
|
self.name = None
|
|
34
36
|
self.layout = {}
|
|
37
|
+
self.schema = {}
|
|
35
38
|
|
|
36
39
|
def to_dict(self) -> dict:
|
|
37
40
|
"""
|
|
@@ -42,7 +45,8 @@ class AgentItem:
|
|
|
42
45
|
return {
|
|
43
46
|
"id": self.id,
|
|
44
47
|
"name": self.name,
|
|
45
|
-
"layout": self.layout
|
|
48
|
+
"layout": self.layout,
|
|
49
|
+
"schema": self.schema,
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
def dump(self) -> str:
|
pygpt_net/item/preset.py
CHANGED
|
@@ -215,11 +215,29 @@ class PresetItem:
|
|
|
215
215
|
if "user_name" in data:
|
|
216
216
|
self.user_name = data["user_name"]
|
|
217
217
|
if "uuid" in data:
|
|
218
|
-
self.uuid = uuid.UUID(data["uuid"])
|
|
218
|
+
self.uuid = str(uuid.UUID(data["uuid"]))
|
|
219
219
|
if "vision" in data:
|
|
220
220
|
self.vision = data["vision"]
|
|
221
221
|
return self
|
|
222
222
|
|
|
223
|
+
def reset_modes(self):
|
|
224
|
+
"""
|
|
225
|
+
Reset modes
|
|
226
|
+
"""
|
|
227
|
+
self.agent = False
|
|
228
|
+
self.agent_llama = False
|
|
229
|
+
self.agent_openai = False
|
|
230
|
+
self.audio = False
|
|
231
|
+
self.assistant = False
|
|
232
|
+
self.chat = False
|
|
233
|
+
self.completion = False
|
|
234
|
+
self.computer = False
|
|
235
|
+
self.expert = False
|
|
236
|
+
self.langchain = False
|
|
237
|
+
self.llama_index = False
|
|
238
|
+
self.research = False
|
|
239
|
+
self.vision = False
|
|
240
|
+
|
|
223
241
|
def add_function(self, name: str, parameters: str, desc: str):
|
|
224
242
|
"""
|
|
225
243
|
Add function to preset
|