deepanalysts 0.7.2__tar.gz → 0.7.4__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.
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/PKG-INFO +5 -5
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/__init__.py +13 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/composite.py +39 -9
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/supabase_storage.py +8 -2
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/__init__.py +16 -1
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/filesystem.py +10 -4
- deepanalysts-0.7.4/deepanalysts/middleware/summarization.py +681 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts.egg-info/PKG-INFO +5 -5
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts.egg-info/requires.txt +4 -4
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/pyproject.toml +11 -12
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_composite_backend.py +89 -4
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_filesystem_middleware.py +35 -0
- deepanalysts-0.7.4/tests/test_summarization_middleware.py +581 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_supabase_storage_backend.py +35 -0
- deepanalysts-0.7.2/deepanalysts/middleware/summarization.py +0 -752
- deepanalysts-0.7.2/tests/test_summarization_middleware.py +0 -337
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/README.md +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/_messages_reducer.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/__init__.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/basement.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/e2b.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/filesystem.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/protocol.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/sandbox.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/state.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/store.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/backends/utils.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/clients/__init__.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/clients/basement.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/_state.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/_utils.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/memory.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/patch_tool_calls.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/skills.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/subagents.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/middleware/tool_errors.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/state.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/streaming.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/utils/__init__.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts/utils/retry.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts.egg-info/SOURCES.txt +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts.egg-info/dependency_links.txt +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/deepanalysts.egg-info/top_level.txt +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/setup.cfg +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_basement.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_e2b_backend.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_e2b_integration.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_messages_reducer.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_prompt_sections.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_protocol_bridge.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_regression_files_delta.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_regression_fs_backport.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_regression_middleware_tools.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_regression_new_api.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_regression_subagents.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_regression_tier1_backports.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_sandbox_backend.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_sandbox_hardening.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_sandbox_hardening_integration.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_skills_middleware.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_store_backend.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_streaming_transformer.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_supabase_storage_integration.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_tool_errors.py +0 -0
- {deepanalysts-0.7.2 → deepanalysts-0.7.4}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepanalysts
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: LangChain/LangGraph middleware for building AI agents with memory, skills, and filesystem support
|
|
5
5
|
Author-email: Ganchuluun Narantsatsralt <tsatsralt@swifttech.cloud>
|
|
6
6
|
License: MIT
|
|
@@ -18,15 +18,15 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
18
18
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
19
|
Requires-Python: <4.0,>=3.11
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
|
-
Requires-Dist: langchain<2.0.0,>=1.3.
|
|
22
|
-
Requires-Dist: langchain-core<2.0.0,>=1.4.
|
|
23
|
-
Requires-Dist: langgraph>=1.2.
|
|
21
|
+
Requires-Dist: langchain<2.0.0,>=1.3.13
|
|
22
|
+
Requires-Dist: langchain-core<2.0.0,>=1.4.9
|
|
23
|
+
Requires-Dist: langgraph>=1.2.9
|
|
24
24
|
Requires-Dist: httpx>=0.28.0
|
|
25
25
|
Requires-Dist: pyyaml>=6.0
|
|
26
26
|
Requires-Dist: tenacity>=8.2.0
|
|
27
27
|
Requires-Dist: wcmatch>=8.5.0
|
|
28
28
|
Provides-Extra: postgres
|
|
29
|
-
Requires-Dist: langgraph-checkpoint-postgres>=
|
|
29
|
+
Requires-Dist: langgraph-checkpoint-postgres>=3.1.0; extra == "postgres"
|
|
30
30
|
Requires-Dist: psycopg[binary,pool]>=3.2.0; extra == "postgres"
|
|
31
31
|
Provides-Extra: e2b
|
|
32
32
|
Requires-Dist: e2b>=1.0.0; extra == "e2b"
|
|
@@ -35,9 +35,15 @@ from deepanalysts.middleware import (
|
|
|
35
35
|
SkillsMiddleware,
|
|
36
36
|
SubAgent,
|
|
37
37
|
SubAgentMiddleware,
|
|
38
|
+
SummarizationDefaults,
|
|
39
|
+
SummarizationEvent,
|
|
38
40
|
SummarizationMiddleware,
|
|
41
|
+
SummarizationState,
|
|
39
42
|
ToolErrorHandlingMiddleware,
|
|
43
|
+
TriggerClause,
|
|
40
44
|
TruncateArgsSettings,
|
|
45
|
+
compute_summarization_defaults,
|
|
46
|
+
create_summarization_middleware,
|
|
41
47
|
)
|
|
42
48
|
from deepanalysts.state import DEFAULT_SNAPSHOT_FREQUENCY, DeepAnalystsState
|
|
43
49
|
from deepanalysts.streaming import (
|
|
@@ -66,8 +72,15 @@ __all__ = [
|
|
|
66
72
|
"CompiledSubAgent",
|
|
67
73
|
"SkillMetadata",
|
|
68
74
|
"SubAgent",
|
|
75
|
+
"SummarizationDefaults",
|
|
76
|
+
"SummarizationEvent",
|
|
77
|
+
"SummarizationState",
|
|
78
|
+
"TriggerClause",
|
|
69
79
|
"TruncateArgsSettings",
|
|
70
80
|
# Constants
|
|
71
81
|
"TASK_SYSTEM_PROMPT",
|
|
72
82
|
"TASK_TOOL_DESCRIPTION",
|
|
83
|
+
# Helpers
|
|
84
|
+
"compute_summarization_defaults",
|
|
85
|
+
"create_summarization_middleware",
|
|
73
86
|
]
|
|
@@ -9,7 +9,8 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
import asyncio
|
|
11
11
|
from collections import defaultdict
|
|
12
|
-
from
|
|
12
|
+
from dataclasses import replace
|
|
13
|
+
from typing import TypeVar, cast
|
|
13
14
|
|
|
14
15
|
from deepanalysts.backends.protocol import (
|
|
15
16
|
BackendProtocol,
|
|
@@ -49,6 +50,29 @@ def _remap_file_info_path(fi: FileInfo, route_prefix: str) -> FileInfo:
|
|
|
49
50
|
)
|
|
50
51
|
|
|
51
52
|
|
|
53
|
+
_ResultT = TypeVar("_ResultT", WriteResult, EditResult)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _remap_result_paths(res: _ResultT, route_prefix: str | None) -> _ResultT:
|
|
57
|
+
"""Re-prepend a matched route prefix to a write/edit result's paths.
|
|
58
|
+
|
|
59
|
+
Child backends receive route-stripped paths, so the ``path`` (and
|
|
60
|
+
``files_update`` keys) they return are relative to the route root. Tool
|
|
61
|
+
confirmations echo ``res.path`` back to the model — leaving it stripped
|
|
62
|
+
hands the model a path that routes to a *different* backend on the next
|
|
63
|
+
call (e.g. ``/shared/x.md`` written, ``/x.md`` echoed, follow-up read of
|
|
64
|
+
``/x.md`` hits the default sandbox and fails).
|
|
65
|
+
"""
|
|
66
|
+
if route_prefix is None:
|
|
67
|
+
return res
|
|
68
|
+
prefix = route_prefix.rstrip("/")
|
|
69
|
+
path = f"{prefix}{res.path}" if res.path else res.path
|
|
70
|
+
files_update = res.files_update
|
|
71
|
+
if files_update is not None:
|
|
72
|
+
files_update = {f"{prefix}{k}": v for k, v in files_update.items()}
|
|
73
|
+
return replace(res, path=path, files_update=files_update)
|
|
74
|
+
|
|
75
|
+
|
|
52
76
|
def _strip_route_from_pattern(pattern: str, route_prefix: str) -> str:
|
|
53
77
|
"""Strip a route prefix from a glob pattern when the pattern targets that route.
|
|
54
78
|
|
|
@@ -163,8 +187,8 @@ class CompositeBackend(SandboxBackendProtocol):
|
|
|
163
187
|
return backend.read(backend_path, offset=offset, limit=limit)
|
|
164
188
|
|
|
165
189
|
def write(self, file_path: str, content: str) -> WriteResult:
|
|
166
|
-
backend, backend_path,
|
|
167
|
-
return backend.write(backend_path, content)
|
|
190
|
+
backend, backend_path, route_prefix = self._route(file_path)
|
|
191
|
+
return _remap_result_paths(backend.write(backend_path, content), route_prefix)
|
|
168
192
|
|
|
169
193
|
def edit(
|
|
170
194
|
self,
|
|
@@ -173,8 +197,11 @@ class CompositeBackend(SandboxBackendProtocol):
|
|
|
173
197
|
new_string: str,
|
|
174
198
|
replace_all: bool = False,
|
|
175
199
|
) -> EditResult:
|
|
176
|
-
backend, backend_path,
|
|
177
|
-
return
|
|
200
|
+
backend, backend_path, route_prefix = self._route(file_path)
|
|
201
|
+
return _remap_result_paths(
|
|
202
|
+
backend.edit(backend_path, old_string, new_string, replace_all=replace_all),
|
|
203
|
+
route_prefix,
|
|
204
|
+
)
|
|
178
205
|
|
|
179
206
|
def grep(
|
|
180
207
|
self,
|
|
@@ -309,8 +336,8 @@ class CompositeBackend(SandboxBackendProtocol):
|
|
|
309
336
|
return await backend.aread_result(backend_path, offset=offset, limit=limit)
|
|
310
337
|
|
|
311
338
|
async def awrite(self, file_path: str, content: str) -> WriteResult:
|
|
312
|
-
backend, backend_path,
|
|
313
|
-
return await backend.awrite(backend_path, content)
|
|
339
|
+
backend, backend_path, route_prefix = self._route(file_path)
|
|
340
|
+
return _remap_result_paths(await backend.awrite(backend_path, content), route_prefix)
|
|
314
341
|
|
|
315
342
|
async def aedit(
|
|
316
343
|
self,
|
|
@@ -319,8 +346,11 @@ class CompositeBackend(SandboxBackendProtocol):
|
|
|
319
346
|
new_string: str,
|
|
320
347
|
replace_all: bool = False,
|
|
321
348
|
) -> EditResult:
|
|
322
|
-
backend, backend_path,
|
|
323
|
-
return
|
|
349
|
+
backend, backend_path, route_prefix = self._route(file_path)
|
|
350
|
+
return _remap_result_paths(
|
|
351
|
+
await backend.aedit(backend_path, old_string, new_string, replace_all=replace_all),
|
|
352
|
+
route_prefix,
|
|
353
|
+
)
|
|
324
354
|
|
|
325
355
|
async def agrep(
|
|
326
356
|
self,
|
|
@@ -337,6 +337,12 @@ class SupabaseStorageBackend(BackendProtocol):
|
|
|
337
337
|
except StorageListError as e:
|
|
338
338
|
return LsResult(error=f"Error: {e}")
|
|
339
339
|
|
|
340
|
+
# Entries must carry the full virtual path, not the bare object name —
|
|
341
|
+
# listing "/research/x/" with entries rendered as "/README.md" reads as
|
|
342
|
+
# a root-level file and the model then read_files the wrong path.
|
|
343
|
+
base = "/" + path.strip("/")
|
|
344
|
+
base = base if base == "/" else f"{base}/"
|
|
345
|
+
|
|
340
346
|
entries: list[FileInfo] = []
|
|
341
347
|
for item in items:
|
|
342
348
|
name = item.get("name", "")
|
|
@@ -344,12 +350,12 @@ class SupabaseStorageBackend(BackendProtocol):
|
|
|
344
350
|
continue
|
|
345
351
|
|
|
346
352
|
if item.get("id") is None:
|
|
347
|
-
entries.append(FileInfo(path=f"
|
|
353
|
+
entries.append(FileInfo(path=f"{base}{name}/", is_dir=True, size=0, modified_at=""))
|
|
348
354
|
else:
|
|
349
355
|
metadata = item.get("metadata") or {}
|
|
350
356
|
entries.append(
|
|
351
357
|
FileInfo(
|
|
352
|
-
path=f"
|
|
358
|
+
path=f"{base}{name}",
|
|
353
359
|
is_dir=False,
|
|
354
360
|
size=metadata.get("size", 0),
|
|
355
361
|
modified_at=item.get("updated_at", ""),
|
|
@@ -12,7 +12,16 @@ from deepanalysts.middleware.subagents import (
|
|
|
12
12
|
SubAgent,
|
|
13
13
|
SubAgentMiddleware,
|
|
14
14
|
)
|
|
15
|
-
from deepanalysts.middleware.summarization import
|
|
15
|
+
from deepanalysts.middleware.summarization import (
|
|
16
|
+
SummarizationDefaults,
|
|
17
|
+
SummarizationEvent,
|
|
18
|
+
SummarizationMiddleware,
|
|
19
|
+
SummarizationState,
|
|
20
|
+
TriggerClause,
|
|
21
|
+
TruncateArgsSettings,
|
|
22
|
+
compute_summarization_defaults,
|
|
23
|
+
create_summarization_middleware,
|
|
24
|
+
)
|
|
16
25
|
from deepanalysts.middleware.tool_errors import ToolErrorHandlingMiddleware
|
|
17
26
|
|
|
18
27
|
__all__ = [
|
|
@@ -28,10 +37,16 @@ __all__ = [
|
|
|
28
37
|
"CompiledSubAgent",
|
|
29
38
|
"SkillMetadata",
|
|
30
39
|
"SubAgent",
|
|
40
|
+
"SummarizationDefaults",
|
|
41
|
+
"SummarizationEvent",
|
|
42
|
+
"SummarizationState",
|
|
43
|
+
"TriggerClause",
|
|
31
44
|
"TruncateArgsSettings",
|
|
32
45
|
# Constants
|
|
33
46
|
"TASK_SYSTEM_PROMPT",
|
|
34
47
|
"TASK_TOOL_DESCRIPTION",
|
|
35
48
|
# Helpers
|
|
49
|
+
"compute_summarization_defaults",
|
|
50
|
+
"create_summarization_middleware",
|
|
36
51
|
"private_state_field_names",
|
|
37
52
|
]
|
|
@@ -736,19 +736,22 @@ class FilesystemMiddleware(AgentMiddleware):
|
|
|
736
736
|
res: WriteResult = resolved_backend.write(file_path, content)
|
|
737
737
|
if res.error:
|
|
738
738
|
return res.error
|
|
739
|
+
# Byte count lets the model verify a large write completed even
|
|
740
|
+
# after history compaction truncates the content argument.
|
|
741
|
+
confirmation = f"Updated file {res.path} ({len(content.encode('utf-8'))} bytes written)"
|
|
739
742
|
if res.files_update is not None:
|
|
740
743
|
return Command(
|
|
741
744
|
update={
|
|
742
745
|
"files": res.files_update,
|
|
743
746
|
"messages": [
|
|
744
747
|
ToolMessage(
|
|
745
|
-
content=
|
|
748
|
+
content=confirmation,
|
|
746
749
|
tool_call_id=runtime.tool_call_id,
|
|
747
750
|
)
|
|
748
751
|
],
|
|
749
752
|
}
|
|
750
753
|
)
|
|
751
|
-
return
|
|
754
|
+
return confirmation
|
|
752
755
|
|
|
753
756
|
async def async_write_file(
|
|
754
757
|
file_path: Annotated[str, "Absolute path to the file to write."],
|
|
@@ -763,19 +766,22 @@ class FilesystemMiddleware(AgentMiddleware):
|
|
|
763
766
|
res: WriteResult = await resolved_backend.awrite(file_path, content)
|
|
764
767
|
if res.error:
|
|
765
768
|
return res.error
|
|
769
|
+
# Byte count lets the model verify a large write completed even
|
|
770
|
+
# after history compaction truncates the content argument.
|
|
771
|
+
confirmation = f"Updated file {res.path} ({len(content.encode('utf-8'))} bytes written)"
|
|
766
772
|
if res.files_update is not None:
|
|
767
773
|
return Command(
|
|
768
774
|
update={
|
|
769
775
|
"files": res.files_update,
|
|
770
776
|
"messages": [
|
|
771
777
|
ToolMessage(
|
|
772
|
-
content=
|
|
778
|
+
content=confirmation,
|
|
773
779
|
tool_call_id=runtime.tool_call_id,
|
|
774
780
|
)
|
|
775
781
|
],
|
|
776
782
|
}
|
|
777
783
|
)
|
|
778
|
-
return
|
|
784
|
+
return confirmation
|
|
779
785
|
|
|
780
786
|
return StructuredTool.from_function(
|
|
781
787
|
name="write_file",
|