nucliadb-agentic-api 1.0.0.post226__tar.gz → 1.0.0.post240__tar.gz
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.
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/PKG-INFO +1 -1
- nucliadb_agentic_api-1.0.0.post240/VERSION +1 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/pyproject.toml +1 -1
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/pyproject.toml.orig +1 -1
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/db/transform.py +90 -88
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/ask_websocket.py +19 -0
- nucliadb_agentic_api-1.0.0.post226/VERSION +0 -1
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/README.md +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/alembic/README +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/alembic/env.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/alembic/script.py.mako +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/alembic/versions/7f3b2f92a8c1_add_agentic_config_table.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/alembic/versions/b3c4d5e6f7a8_add_sources_table.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/alembic/versions/c4d5e6f7a8b9_add_agentic_config_soft_deletion.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/alembic.ini +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/VERSION +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/__init__.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/agentic/__init__.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/agentic/ask_handler.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/agentic/ask_result.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/agentic/ask_transform_to_interaction.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/app.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/commands.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/db/__init__.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/db/agentic_configs.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/db/settings.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/db/sources.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/exceptions.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/logging.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/models.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/py.typed +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/server/__init__.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/server/server.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/server/session.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/server/settings.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/settings.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/utils.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/__init__.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/agentic_configs.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/ask.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/mcp_content.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/mcp_nucliadb.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/oauth.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/router.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/sources.py +0 -0
- {nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/src/nucliadb_agentic_api/v1/utils.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.0.post240
|
{nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/pyproject.toml.orig
RENAMED
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nucliadb_agentic_api"
|
|
7
|
-
version = "1.0.0.
|
|
7
|
+
version = "1.0.0.post240"
|
|
8
8
|
authors = [{ name = "AI Data Team", email = "learning@nuclia.com" }]
|
|
9
9
|
description = "NucliaDB Agentic API for Hyperforge"
|
|
10
10
|
readme = "README.md"
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Dict, Tuple
|
|
2
2
|
from uuid import uuid4
|
|
3
3
|
|
|
4
|
+
from hyperforge.agent import AgentConfig
|
|
5
|
+
from hyperforge.context.config import ContextAgentConfig
|
|
4
6
|
from hyperforge.driver import DriverConfig
|
|
5
7
|
from hyperforge.models import MemoryConfig, Rules
|
|
6
8
|
from hyperforge.retrieval.config import RetrievalAgentConfig
|
|
7
9
|
from hyperforge.workflows import WorkflowData
|
|
8
|
-
from
|
|
10
|
+
from hyperforge_google.config import GoogleAgentConfig
|
|
11
|
+
from hyperforge_mcp.config import MCPAgentConfig, Transport
|
|
9
12
|
from hyperforge_mcp.config_driver import (
|
|
10
13
|
MCPHTTPDriverConfig,
|
|
11
14
|
MCPHTTPInnerConfig,
|
|
@@ -14,10 +17,15 @@ from hyperforge_nucliadb.driver_config import (
|
|
|
14
17
|
NucliaDBConfig,
|
|
15
18
|
NucliaDBConnection,
|
|
16
19
|
)
|
|
20
|
+
from hyperforge_nucliadb_agentic.config import NucliaDBAgentConfig
|
|
17
21
|
from hyperforge_nucliadb_agentic.internal_driver import (
|
|
18
22
|
InternalNucliaDBConfig,
|
|
19
23
|
InternalNucliaDBConnection,
|
|
20
24
|
)
|
|
25
|
+
from hyperforge_perplexity.config import PerplexityAgentConfig
|
|
26
|
+
from hyperforge_rephrase.config import RephraseAgentConfig
|
|
27
|
+
from hyperforge_smart.config import SmartAgentConfig
|
|
28
|
+
from hyperforge_summarize.config import SummarizeAgentConfig
|
|
21
29
|
|
|
22
30
|
from nucliadb_agentic_api.db.sources import Sources
|
|
23
31
|
from nucliadb_agentic_api.models import AgenticConfigSchema
|
|
@@ -43,60 +51,35 @@ async def transform_agentic_config(
|
|
|
43
51
|
global_driver = []
|
|
44
52
|
|
|
45
53
|
title = agentic_config.title if agentic_config.title else "Default Agentic Config"
|
|
54
|
+
preprocess: list[AgentConfig] = []
|
|
55
|
+
context: list[AgentConfig] = []
|
|
56
|
+
generation: list[AgentConfig] = []
|
|
46
57
|
|
|
47
58
|
if agentic_config.rephrase:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if agentic_config.rephrase.history is not None:
|
|
59
|
-
config["history"] = agentic_config.rephrase.history
|
|
60
|
-
|
|
61
|
-
config["module"] = "rephrase"
|
|
62
|
-
preprocess = [config]
|
|
63
|
-
else:
|
|
64
|
-
preprocess = []
|
|
59
|
+
rephrase = agentic_config.rephrase
|
|
60
|
+
rephrase_config = RephraseAgentConfig(
|
|
61
|
+
title=f"{title} - Retrieval",
|
|
62
|
+
rules=[rephrase.prompt] if rephrase.prompt else None,
|
|
63
|
+
kb=rephrase.ask_to,
|
|
64
|
+
history=rephrase.history if rephrase.history is not None else False,
|
|
65
|
+
)
|
|
66
|
+
if rephrase.model:
|
|
67
|
+
rephrase_config.model = rephrase.model
|
|
68
|
+
preprocess.append(rephrase_config)
|
|
65
69
|
|
|
66
70
|
if agentic_config.smart_agent:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if agentic_config.smart_agent.extra_prompt:
|
|
71
|
-
config["extra_prompt"] = agentic_config.smart_agent.extra_prompt
|
|
72
|
-
if agentic_config.smart_agent.models:
|
|
73
|
-
if agentic_config.smart_agent.models.context_validation:
|
|
74
|
-
config["context_validation_model"] = (
|
|
75
|
-
agentic_config.smart_agent.models.context_validation
|
|
76
|
-
)
|
|
77
|
-
if agentic_config.smart_agent.models.planner:
|
|
78
|
-
config["planner_model"] = agentic_config.smart_agent.models.planner
|
|
79
|
-
if agentic_config.smart_agent.models.executor:
|
|
80
|
-
config["executor_model"] = agentic_config.smart_agent.models.executor
|
|
81
|
-
if agentic_config.smart_agent.extra_prompt:
|
|
82
|
-
config["extra_prompt"] = agentic_config.smart_agent.extra_prompt
|
|
83
|
-
if agentic_config.smart_agent.history is not None:
|
|
84
|
-
config["history"] = agentic_config.smart_agent.history
|
|
85
|
-
registered_agents = []
|
|
86
|
-
for source in agentic_config.smart_agent.sources:
|
|
71
|
+
smart_agent = agentic_config.smart_agent
|
|
72
|
+
registered_agents: list[ContextAgentConfig] = []
|
|
73
|
+
for source in smart_agent.sources:
|
|
87
74
|
source_obj = await source_manager.get_source(account, kbid, source)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
source_title = (
|
|
76
|
+
f"{title} - Smart Agent - {source_obj.type.capitalize()} Source"
|
|
77
|
+
)
|
|
91
78
|
|
|
92
79
|
if source_obj.type == "nucliadb":
|
|
93
80
|
# Same KB different
|
|
94
81
|
uid = uuid4().hex
|
|
95
82
|
|
|
96
|
-
source_config["id"] = f"nucliadb-agent-{source}"
|
|
97
|
-
source_config["sources"] = [uid]
|
|
98
|
-
source_config["module"] = "nucliadb_agent"
|
|
99
|
-
|
|
100
83
|
ndb_driver_config: DriverConfig
|
|
101
84
|
if internal_nucliadb and internal_nucliadb_url:
|
|
102
85
|
ndb_driver_config = InternalNucliaDBConfig(
|
|
@@ -137,15 +120,13 @@ async def transform_agentic_config(
|
|
|
137
120
|
"No NucliaDB URL configured for internal or external access"
|
|
138
121
|
)
|
|
139
122
|
drivers[uid] = ndb_driver_config
|
|
140
|
-
registered_agents.append(
|
|
123
|
+
registered_agents.append(
|
|
124
|
+
NucliaDBAgentConfig(
|
|
125
|
+
id=f"nucliadb-agent-{source}", title=source_title, sources=[uid]
|
|
126
|
+
)
|
|
127
|
+
)
|
|
141
128
|
elif source_obj.type == "mcp":
|
|
142
129
|
uid = uuid4().hex
|
|
143
|
-
# See the nucliadb branch above for why this must be
|
|
144
|
-
# deterministic rather than random.
|
|
145
|
-
source_config["id"] = f"mcp-agent-{source}"
|
|
146
|
-
source_config["sources"] = [uid]
|
|
147
|
-
source_config["transport"] = Transport.HTTP
|
|
148
|
-
source_config["module"] = "mcp"
|
|
149
130
|
mcp_driver_config = MCPHTTPDriverConfig(
|
|
150
131
|
identifier=uid,
|
|
151
132
|
name="MCPHTTP",
|
|
@@ -156,47 +137,68 @@ async def transform_agentic_config(
|
|
|
156
137
|
),
|
|
157
138
|
) # TODO: pass real config if needed
|
|
158
139
|
drivers[uid] = mcp_driver_config
|
|
159
|
-
registered_agents.append(
|
|
140
|
+
registered_agents.append(
|
|
141
|
+
MCPAgentConfig(
|
|
142
|
+
id=f"mcp-agent-{source}",
|
|
143
|
+
title=source_title,
|
|
144
|
+
source=uid,
|
|
145
|
+
transport=Transport.HTTP,
|
|
146
|
+
tool_choice_model=source_obj.tool_choice_model or "chatgpt-4.1",
|
|
147
|
+
valid_headers=source_obj.valid_headers or [],
|
|
148
|
+
)
|
|
149
|
+
)
|
|
160
150
|
|
|
161
151
|
elif source_obj.type == "google":
|
|
162
|
-
source_config["id"] = f"google-agent-{source}"
|
|
163
|
-
source_config["module"] = "google"
|
|
164
152
|
global_driver.append("google")
|
|
165
|
-
registered_agents.append(
|
|
153
|
+
registered_agents.append(
|
|
154
|
+
GoogleAgentConfig(id=f"google-agent-{source}", title=source_title)
|
|
155
|
+
)
|
|
166
156
|
|
|
167
157
|
elif source_obj.type == "perplexity":
|
|
168
|
-
source_config["id"] = f"perplexity-agent-{source}"
|
|
169
|
-
source_config["module"] = "perplexity"
|
|
170
158
|
global_driver.append("perplexity")
|
|
171
|
-
registered_agents.append(
|
|
159
|
+
registered_agents.append(
|
|
160
|
+
PerplexityAgentConfig(
|
|
161
|
+
id=f"perplexity-agent-{source}",
|
|
162
|
+
title=source_title,
|
|
163
|
+
domain=source_obj.enabled_domains or [],
|
|
164
|
+
prompt=None,
|
|
165
|
+
)
|
|
166
|
+
)
|
|
172
167
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
168
|
+
models = smart_agent.models
|
|
169
|
+
smart_config = SmartAgentConfig(
|
|
170
|
+
title=f"{title} - Smart Agent",
|
|
171
|
+
planning_mode=smart_agent.mode.value,
|
|
172
|
+
extra_prompt=smart_agent.extra_prompt,
|
|
173
|
+
history=smart_agent.history if smart_agent.history is not None else False,
|
|
174
|
+
# SmartAgentConfig's before-validator accepts serialized agent configs.
|
|
175
|
+
registered_agents=[agent.model_dump() for agent in registered_agents], # type: ignore[misc]
|
|
176
|
+
)
|
|
177
|
+
# Only set the models if they are provided; otherwise, leave them as None to use hyperforge's default models.
|
|
178
|
+
# TODO: Provide nucliadb agentic api level defaults for models
|
|
179
|
+
if models:
|
|
180
|
+
if models.context_validation:
|
|
181
|
+
smart_config.context_validation_model = models.context_validation
|
|
182
|
+
if models.planner:
|
|
183
|
+
smart_config.planner_model = models.planner
|
|
184
|
+
if models.executor:
|
|
185
|
+
smart_config.executor_model = models.executor
|
|
186
|
+
context.append(smart_config)
|
|
178
187
|
|
|
179
188
|
if agentic_config.summarize:
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
config["history"] = agentic_config.summarize.history
|
|
194
|
-
|
|
195
|
-
config["module"] = "summarize"
|
|
196
|
-
|
|
197
|
-
generation = [config]
|
|
198
|
-
else:
|
|
199
|
-
generation = []
|
|
189
|
+
summarize = agentic_config.summarize
|
|
190
|
+
summarize_config = SummarizeAgentConfig(
|
|
191
|
+
title=f"{title} - Summarize Agent",
|
|
192
|
+
prompt=summarize.user_prompt,
|
|
193
|
+
system_prompt=summarize.system_prompt,
|
|
194
|
+
conversational=summarize.conversational,
|
|
195
|
+
citations=True,
|
|
196
|
+
force_chunk_level_citations=False,
|
|
197
|
+
history=summarize.history if summarize.history is not None else False,
|
|
198
|
+
)
|
|
199
|
+
if summarize.model:
|
|
200
|
+
summarize_config.model = summarize.model
|
|
201
|
+
generation.append(summarize_config)
|
|
200
202
|
|
|
201
203
|
return (
|
|
202
204
|
RetrievalAgentConfig(
|
|
@@ -209,9 +211,9 @@ async def transform_agentic_config(
|
|
|
209
211
|
description="Default workflow for agentic config transformation",
|
|
210
212
|
parameters=None,
|
|
211
213
|
),
|
|
212
|
-
preprocess=preprocess,
|
|
213
|
-
context=context,
|
|
214
|
-
generation=generation,
|
|
214
|
+
preprocess=preprocess,
|
|
215
|
+
context=context,
|
|
216
|
+
generation=generation,
|
|
215
217
|
postprocess=[],
|
|
216
218
|
),
|
|
217
219
|
drivers,
|
|
@@ -5,6 +5,7 @@ from fastapi import Header, Query, WebSocket, WebSocketDisconnect
|
|
|
5
5
|
from hyperforge.api.authentication import requires
|
|
6
6
|
from hyperforge.api.v1.interaction import WebsocketReceiver, stream_response
|
|
7
7
|
from hyperforge.interaction import AnswerOperation, AragAnswer, ARAGException
|
|
8
|
+
from hyperforge_nucliadb_agentic.ask.audit import get_audit, get_trace_id
|
|
8
9
|
from hyperforge_nucliadb_agentic.ask.model import (
|
|
9
10
|
AskRequest,
|
|
10
11
|
)
|
|
@@ -21,6 +22,7 @@ from nucliadb_models.security import RequestSecurity
|
|
|
21
22
|
from nucliadb_utils.authentication import NucliaUser
|
|
22
23
|
from pydantic import ValidationError
|
|
23
24
|
|
|
25
|
+
from nucliadb_agentic_api import logger
|
|
24
26
|
from nucliadb_agentic_api.v1.router import router
|
|
25
27
|
|
|
26
28
|
|
|
@@ -127,6 +129,23 @@ async def websocket_endpoint(
|
|
|
127
129
|
interaction,
|
|
128
130
|
workflow_id=agentic_config_id,
|
|
129
131
|
):
|
|
132
|
+
if msg.step and msg.step.external_usage:
|
|
133
|
+
audit = get_audit()
|
|
134
|
+
if audit is not None:
|
|
135
|
+
audit.report_step_usage(
|
|
136
|
+
account_id=x_stf_account,
|
|
137
|
+
kbid=kbid,
|
|
138
|
+
client_type=x_ndb_client,
|
|
139
|
+
step=msg.step,
|
|
140
|
+
trace_id=get_trace_id(),
|
|
141
|
+
)
|
|
142
|
+
else:
|
|
143
|
+
logger.warning(
|
|
144
|
+
"Skipping WebSocket external usage report because audit utility is unavailable account=%s kb=%s module=%s",
|
|
145
|
+
x_stf_account,
|
|
146
|
+
kbid,
|
|
147
|
+
msg.step.module,
|
|
148
|
+
)
|
|
130
149
|
try:
|
|
131
150
|
await websocket.send_text(msg.model_dump_json())
|
|
132
151
|
except (RuntimeError, WebSocketDisconnect):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.0.0.post226
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nucliadb_agentic_api-1.0.0.post226 → nucliadb_agentic_api-1.0.0.post240}/alembic/script.py.mako
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|