basic-memory 0.7.0__py3-none-any.whl → 0.17.4__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.
Potentially problematic release.
This version of basic-memory might be problematic. Click here for more details.
- basic_memory/__init__.py +5 -1
- basic_memory/alembic/alembic.ini +119 -0
- basic_memory/alembic/env.py +130 -20
- basic_memory/alembic/migrations.py +4 -9
- basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +131 -0
- basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +51 -0
- basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +120 -0
- basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +112 -0
- basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +24 -0
- basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +49 -0
- basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +49 -0
- basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +56 -0
- basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +44 -0
- basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +113 -0
- basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +37 -0
- basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +239 -0
- basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +173 -0
- basic_memory/api/app.py +87 -20
- basic_memory/api/container.py +133 -0
- basic_memory/api/routers/__init__.py +4 -1
- basic_memory/api/routers/directory_router.py +84 -0
- basic_memory/api/routers/importer_router.py +152 -0
- basic_memory/api/routers/knowledge_router.py +180 -23
- basic_memory/api/routers/management_router.py +80 -0
- basic_memory/api/routers/memory_router.py +9 -64
- basic_memory/api/routers/project_router.py +460 -0
- basic_memory/api/routers/prompt_router.py +260 -0
- basic_memory/api/routers/resource_router.py +136 -11
- basic_memory/api/routers/search_router.py +5 -5
- basic_memory/api/routers/utils.py +169 -0
- basic_memory/api/template_loader.py +292 -0
- basic_memory/api/v2/__init__.py +35 -0
- basic_memory/api/v2/routers/__init__.py +21 -0
- basic_memory/api/v2/routers/directory_router.py +93 -0
- basic_memory/api/v2/routers/importer_router.py +181 -0
- basic_memory/api/v2/routers/knowledge_router.py +427 -0
- basic_memory/api/v2/routers/memory_router.py +130 -0
- basic_memory/api/v2/routers/project_router.py +359 -0
- basic_memory/api/v2/routers/prompt_router.py +269 -0
- basic_memory/api/v2/routers/resource_router.py +286 -0
- basic_memory/api/v2/routers/search_router.py +73 -0
- basic_memory/cli/app.py +80 -10
- basic_memory/cli/auth.py +300 -0
- basic_memory/cli/commands/__init__.py +15 -2
- basic_memory/cli/commands/cloud/__init__.py +6 -0
- basic_memory/cli/commands/cloud/api_client.py +127 -0
- basic_memory/cli/commands/cloud/bisync_commands.py +110 -0
- basic_memory/cli/commands/cloud/cloud_utils.py +108 -0
- basic_memory/cli/commands/cloud/core_commands.py +195 -0
- basic_memory/cli/commands/cloud/rclone_commands.py +397 -0
- basic_memory/cli/commands/cloud/rclone_config.py +110 -0
- basic_memory/cli/commands/cloud/rclone_installer.py +263 -0
- basic_memory/cli/commands/cloud/upload.py +240 -0
- basic_memory/cli/commands/cloud/upload_command.py +124 -0
- basic_memory/cli/commands/command_utils.py +99 -0
- basic_memory/cli/commands/db.py +87 -12
- basic_memory/cli/commands/format.py +198 -0
- basic_memory/cli/commands/import_chatgpt.py +47 -223
- basic_memory/cli/commands/import_claude_conversations.py +48 -171
- basic_memory/cli/commands/import_claude_projects.py +53 -160
- basic_memory/cli/commands/import_memory_json.py +55 -111
- basic_memory/cli/commands/mcp.py +67 -11
- basic_memory/cli/commands/project.py +889 -0
- basic_memory/cli/commands/status.py +52 -34
- basic_memory/cli/commands/telemetry.py +81 -0
- basic_memory/cli/commands/tool.py +341 -0
- basic_memory/cli/container.py +84 -0
- basic_memory/cli/main.py +14 -6
- basic_memory/config.py +580 -26
- basic_memory/db.py +285 -28
- basic_memory/deps/__init__.py +293 -0
- basic_memory/deps/config.py +26 -0
- basic_memory/deps/db.py +56 -0
- basic_memory/deps/importers.py +200 -0
- basic_memory/deps/projects.py +238 -0
- basic_memory/deps/repositories.py +179 -0
- basic_memory/deps/services.py +480 -0
- basic_memory/deps.py +16 -185
- basic_memory/file_utils.py +318 -54
- basic_memory/ignore_utils.py +297 -0
- basic_memory/importers/__init__.py +27 -0
- basic_memory/importers/base.py +100 -0
- basic_memory/importers/chatgpt_importer.py +245 -0
- basic_memory/importers/claude_conversations_importer.py +192 -0
- basic_memory/importers/claude_projects_importer.py +184 -0
- basic_memory/importers/memory_json_importer.py +128 -0
- basic_memory/importers/utils.py +61 -0
- basic_memory/markdown/entity_parser.py +182 -23
- basic_memory/markdown/markdown_processor.py +70 -7
- basic_memory/markdown/plugins.py +43 -23
- basic_memory/markdown/schemas.py +1 -1
- basic_memory/markdown/utils.py +38 -14
- basic_memory/mcp/async_client.py +135 -4
- basic_memory/mcp/clients/__init__.py +28 -0
- basic_memory/mcp/clients/directory.py +70 -0
- basic_memory/mcp/clients/knowledge.py +176 -0
- basic_memory/mcp/clients/memory.py +120 -0
- basic_memory/mcp/clients/project.py +89 -0
- basic_memory/mcp/clients/resource.py +71 -0
- basic_memory/mcp/clients/search.py +65 -0
- basic_memory/mcp/container.py +110 -0
- basic_memory/mcp/project_context.py +155 -0
- basic_memory/mcp/prompts/__init__.py +19 -0
- basic_memory/mcp/prompts/ai_assistant_guide.py +70 -0
- basic_memory/mcp/prompts/continue_conversation.py +62 -0
- basic_memory/mcp/prompts/recent_activity.py +188 -0
- basic_memory/mcp/prompts/search.py +57 -0
- basic_memory/mcp/prompts/utils.py +162 -0
- basic_memory/mcp/resources/ai_assistant_guide.md +283 -0
- basic_memory/mcp/resources/project_info.py +71 -0
- basic_memory/mcp/server.py +61 -9
- basic_memory/mcp/tools/__init__.py +33 -21
- basic_memory/mcp/tools/build_context.py +120 -0
- basic_memory/mcp/tools/canvas.py +152 -0
- basic_memory/mcp/tools/chatgpt_tools.py +190 -0
- basic_memory/mcp/tools/delete_note.py +249 -0
- basic_memory/mcp/tools/edit_note.py +325 -0
- basic_memory/mcp/tools/list_directory.py +157 -0
- basic_memory/mcp/tools/move_note.py +549 -0
- basic_memory/mcp/tools/project_management.py +204 -0
- basic_memory/mcp/tools/read_content.py +281 -0
- basic_memory/mcp/tools/read_note.py +265 -0
- basic_memory/mcp/tools/recent_activity.py +528 -0
- basic_memory/mcp/tools/search.py +377 -24
- basic_memory/mcp/tools/utils.py +402 -16
- basic_memory/mcp/tools/view_note.py +78 -0
- basic_memory/mcp/tools/write_note.py +230 -0
- basic_memory/models/__init__.py +3 -2
- basic_memory/models/knowledge.py +82 -17
- basic_memory/models/project.py +93 -0
- basic_memory/models/search.py +68 -8
- basic_memory/project_resolver.py +222 -0
- basic_memory/repository/__init__.py +2 -0
- basic_memory/repository/entity_repository.py +437 -8
- basic_memory/repository/observation_repository.py +36 -3
- basic_memory/repository/postgres_search_repository.py +451 -0
- basic_memory/repository/project_info_repository.py +10 -0
- basic_memory/repository/project_repository.py +140 -0
- basic_memory/repository/relation_repository.py +79 -4
- basic_memory/repository/repository.py +148 -29
- basic_memory/repository/search_index_row.py +95 -0
- basic_memory/repository/search_repository.py +79 -268
- basic_memory/repository/search_repository_base.py +241 -0
- basic_memory/repository/sqlite_search_repository.py +437 -0
- basic_memory/runtime.py +61 -0
- basic_memory/schemas/__init__.py +22 -9
- basic_memory/schemas/base.py +131 -12
- basic_memory/schemas/cloud.py +50 -0
- basic_memory/schemas/directory.py +31 -0
- basic_memory/schemas/importer.py +35 -0
- basic_memory/schemas/memory.py +194 -25
- basic_memory/schemas/project_info.py +213 -0
- basic_memory/schemas/prompt.py +90 -0
- basic_memory/schemas/request.py +56 -2
- basic_memory/schemas/response.py +85 -28
- basic_memory/schemas/search.py +36 -35
- basic_memory/schemas/sync_report.py +72 -0
- basic_memory/schemas/v2/__init__.py +27 -0
- basic_memory/schemas/v2/entity.py +133 -0
- basic_memory/schemas/v2/resource.py +47 -0
- basic_memory/services/__init__.py +2 -1
- basic_memory/services/context_service.py +451 -138
- basic_memory/services/directory_service.py +310 -0
- basic_memory/services/entity_service.py +636 -71
- basic_memory/services/exceptions.py +21 -0
- basic_memory/services/file_service.py +402 -33
- basic_memory/services/initialization.py +216 -0
- basic_memory/services/link_resolver.py +50 -56
- basic_memory/services/project_service.py +888 -0
- basic_memory/services/search_service.py +232 -37
- basic_memory/sync/__init__.py +4 -2
- basic_memory/sync/background_sync.py +26 -0
- basic_memory/sync/coordinator.py +160 -0
- basic_memory/sync/sync_service.py +1200 -109
- basic_memory/sync/watch_service.py +432 -135
- basic_memory/telemetry.py +249 -0
- basic_memory/templates/prompts/continue_conversation.hbs +110 -0
- basic_memory/templates/prompts/search.hbs +101 -0
- basic_memory/utils.py +407 -54
- basic_memory-0.17.4.dist-info/METADATA +617 -0
- basic_memory-0.17.4.dist-info/RECORD +193 -0
- {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/WHEEL +1 -1
- {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/entry_points.txt +1 -0
- basic_memory/alembic/README +0 -1
- basic_memory/cli/commands/sync.py +0 -206
- basic_memory/cli/commands/tools.py +0 -157
- basic_memory/mcp/tools/knowledge.py +0 -68
- basic_memory/mcp/tools/memory.py +0 -170
- basic_memory/mcp/tools/notes.py +0 -202
- basic_memory/schemas/discovery.py +0 -28
- basic_memory/sync/file_change_scanner.py +0 -158
- basic_memory/sync/utils.py +0 -31
- basic_memory-0.7.0.dist-info/METADATA +0 -378
- basic_memory-0.7.0.dist-info/RECORD +0 -82
- {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Pydantic schemas for sync report responses."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import TYPE_CHECKING, Dict, List, Set
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
# avoid cirular imports
|
|
9
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
10
|
+
from basic_memory.sync.sync_service import SyncReport
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SkippedFileResponse(BaseModel):
|
|
14
|
+
"""Information about a file that was skipped due to repeated failures."""
|
|
15
|
+
|
|
16
|
+
path: str = Field(description="File path relative to project root")
|
|
17
|
+
reason: str = Field(description="Error message from last failure")
|
|
18
|
+
failure_count: int = Field(description="Number of consecutive failures")
|
|
19
|
+
first_failed: datetime = Field(description="Timestamp of first failure")
|
|
20
|
+
|
|
21
|
+
model_config = {"from_attributes": True}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SyncReportResponse(BaseModel):
|
|
25
|
+
"""Report of file changes found compared to database state.
|
|
26
|
+
|
|
27
|
+
Used for API responses when scanning or syncing files.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
new: Set[str] = Field(default_factory=set, description="Files on disk but not in database")
|
|
31
|
+
modified: Set[str] = Field(default_factory=set, description="Files with different checksums")
|
|
32
|
+
deleted: Set[str] = Field(default_factory=set, description="Files in database but not on disk")
|
|
33
|
+
moves: Dict[str, str] = Field(
|
|
34
|
+
default_factory=dict, description="Files moved (old_path -> new_path)"
|
|
35
|
+
)
|
|
36
|
+
checksums: Dict[str, str] = Field(
|
|
37
|
+
default_factory=dict, description="Current file checksums (path -> checksum)"
|
|
38
|
+
)
|
|
39
|
+
skipped_files: List[SkippedFileResponse] = Field(
|
|
40
|
+
default_factory=list, description="Files skipped due to repeated failures"
|
|
41
|
+
)
|
|
42
|
+
total: int = Field(description="Total number of changes")
|
|
43
|
+
|
|
44
|
+
@classmethod
|
|
45
|
+
def from_sync_report(cls, report: "SyncReport") -> "SyncReportResponse":
|
|
46
|
+
"""Convert SyncReport dataclass to Pydantic model.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
report: SyncReport dataclass from sync service
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
SyncReportResponse with same data
|
|
53
|
+
"""
|
|
54
|
+
return cls(
|
|
55
|
+
new=report.new,
|
|
56
|
+
modified=report.modified,
|
|
57
|
+
deleted=report.deleted,
|
|
58
|
+
moves=report.moves,
|
|
59
|
+
checksums=report.checksums,
|
|
60
|
+
skipped_files=[
|
|
61
|
+
SkippedFileResponse(
|
|
62
|
+
path=skipped.path,
|
|
63
|
+
reason=skipped.reason,
|
|
64
|
+
failure_count=skipped.failure_count,
|
|
65
|
+
first_failed=skipped.first_failed,
|
|
66
|
+
)
|
|
67
|
+
for skipped in report.skipped_files
|
|
68
|
+
],
|
|
69
|
+
total=report.total,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
model_config = {"from_attributes": True}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""V2 API schemas - ID-based entity and project references."""
|
|
2
|
+
|
|
3
|
+
from basic_memory.schemas.v2.entity import (
|
|
4
|
+
EntityResolveRequest,
|
|
5
|
+
EntityResolveResponse,
|
|
6
|
+
EntityResponseV2,
|
|
7
|
+
MoveEntityRequestV2,
|
|
8
|
+
ProjectResolveRequest,
|
|
9
|
+
ProjectResolveResponse,
|
|
10
|
+
)
|
|
11
|
+
from basic_memory.schemas.v2.resource import (
|
|
12
|
+
CreateResourceRequest,
|
|
13
|
+
UpdateResourceRequest,
|
|
14
|
+
ResourceResponse,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"EntityResolveRequest",
|
|
19
|
+
"EntityResolveResponse",
|
|
20
|
+
"EntityResponseV2",
|
|
21
|
+
"MoveEntityRequestV2",
|
|
22
|
+
"ProjectResolveRequest",
|
|
23
|
+
"ProjectResolveResponse",
|
|
24
|
+
"CreateResourceRequest",
|
|
25
|
+
"UpdateResourceRequest",
|
|
26
|
+
"ResourceResponse",
|
|
27
|
+
]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""V2 entity and project schemas with ID-first design."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Dict, List, Literal, Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
7
|
+
|
|
8
|
+
from basic_memory.schemas.response import ObservationResponse, RelationResponse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EntityResolveRequest(BaseModel):
|
|
12
|
+
"""Request to resolve a string identifier to an entity ID.
|
|
13
|
+
|
|
14
|
+
Supports resolution of:
|
|
15
|
+
- Permalinks (e.g., "specs/search")
|
|
16
|
+
- Titles (e.g., "Search Specification")
|
|
17
|
+
- File paths (e.g., "specs/search.md")
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
identifier: str = Field(
|
|
21
|
+
...,
|
|
22
|
+
description="Entity identifier to resolve (permalink, title, or file path)",
|
|
23
|
+
min_length=1,
|
|
24
|
+
max_length=500,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class EntityResolveResponse(BaseModel):
|
|
29
|
+
"""Response from identifier resolution.
|
|
30
|
+
|
|
31
|
+
Returns the entity ID and associated metadata for the resolved entity.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
external_id: str = Field(..., description="External UUID (primary API identifier)")
|
|
35
|
+
entity_id: int = Field(..., description="Numeric entity ID (internal identifier)")
|
|
36
|
+
permalink: Optional[str] = Field(None, description="Entity permalink")
|
|
37
|
+
file_path: str = Field(..., description="Relative file path")
|
|
38
|
+
title: str = Field(..., description="Entity title")
|
|
39
|
+
resolution_method: Literal["external_id", "permalink", "title", "path", "search"] = Field(
|
|
40
|
+
..., description="How the identifier was resolved"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class MoveEntityRequestV2(BaseModel):
|
|
45
|
+
"""V2 request schema for moving an entity to a new file location.
|
|
46
|
+
|
|
47
|
+
In V2 API, the entity ID is provided in the URL path, so this request
|
|
48
|
+
only needs the destination path.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
destination_path: str = Field(
|
|
52
|
+
...,
|
|
53
|
+
description="New file path for the entity (relative to project root)",
|
|
54
|
+
min_length=1,
|
|
55
|
+
max_length=500,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class EntityResponseV2(BaseModel):
|
|
60
|
+
"""V2 entity response with external_id as the primary API identifier.
|
|
61
|
+
|
|
62
|
+
This response format emphasizes the external_id (UUID) as the primary API identifier,
|
|
63
|
+
with the numeric id maintained for internal reference.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
# External UUID first - this is the primary API identifier in v2
|
|
67
|
+
external_id: str = Field(..., description="External UUID (primary API identifier)")
|
|
68
|
+
# Internal numeric ID
|
|
69
|
+
id: int = Field(..., description="Numeric entity ID (internal identifier)")
|
|
70
|
+
|
|
71
|
+
# Core entity fields
|
|
72
|
+
title: str = Field(..., description="Entity title")
|
|
73
|
+
entity_type: str = Field(..., description="Entity type")
|
|
74
|
+
content_type: str = Field(default="text/markdown", description="Content MIME type")
|
|
75
|
+
|
|
76
|
+
# Secondary identifiers (for compatibility and convenience)
|
|
77
|
+
permalink: Optional[str] = Field(None, description="Entity permalink (may change)")
|
|
78
|
+
file_path: str = Field(..., description="Relative file path (may change)")
|
|
79
|
+
|
|
80
|
+
# Content and metadata
|
|
81
|
+
content: Optional[str] = Field(None, description="Entity content")
|
|
82
|
+
entity_metadata: Optional[Dict] = Field(None, description="Entity metadata")
|
|
83
|
+
|
|
84
|
+
# Relationships
|
|
85
|
+
observations: List[ObservationResponse] = Field(
|
|
86
|
+
default_factory=list, description="Entity observations"
|
|
87
|
+
)
|
|
88
|
+
relations: List[RelationResponse] = Field(default_factory=list, description="Entity relations")
|
|
89
|
+
|
|
90
|
+
# Timestamps
|
|
91
|
+
created_at: datetime = Field(..., description="Creation timestamp")
|
|
92
|
+
updated_at: datetime = Field(..., description="Last update timestamp")
|
|
93
|
+
|
|
94
|
+
# V2-specific metadata
|
|
95
|
+
api_version: Literal["v2"] = Field(
|
|
96
|
+
default="v2", description="API version (always 'v2' for this response)"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
model_config = ConfigDict(from_attributes=True)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class ProjectResolveRequest(BaseModel):
|
|
103
|
+
"""Request to resolve a project identifier to a project ID.
|
|
104
|
+
|
|
105
|
+
Supports resolution of:
|
|
106
|
+
- Project names (e.g., "my-project")
|
|
107
|
+
- Permalinks (e.g., "my-project")
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
identifier: str = Field(
|
|
111
|
+
...,
|
|
112
|
+
description="Project identifier to resolve (name or permalink)",
|
|
113
|
+
min_length=1,
|
|
114
|
+
max_length=255,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class ProjectResolveResponse(BaseModel):
|
|
119
|
+
"""Response from project identifier resolution.
|
|
120
|
+
|
|
121
|
+
Returns the project ID and associated metadata for the resolved project.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
external_id: str = Field(..., description="External UUID (primary API identifier)")
|
|
125
|
+
project_id: int = Field(..., description="Numeric project ID (internal identifier)")
|
|
126
|
+
name: str = Field(..., description="Project name")
|
|
127
|
+
permalink: str = Field(..., description="Project permalink")
|
|
128
|
+
path: str = Field(..., description="Project file path")
|
|
129
|
+
is_active: bool = Field(..., description="Whether the project is active")
|
|
130
|
+
is_default: bool = Field(..., description="Whether the project is the default")
|
|
131
|
+
resolution_method: Literal["external_id", "name", "permalink"] = Field(
|
|
132
|
+
..., description="How the identifier was resolved"
|
|
133
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""V2 resource schemas for file content operations."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CreateResourceRequest(BaseModel):
|
|
7
|
+
"""Request to create a new resource file.
|
|
8
|
+
|
|
9
|
+
File path is required for new resources since we need to know where
|
|
10
|
+
to create the file.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
file_path: str = Field(
|
|
14
|
+
...,
|
|
15
|
+
description="Path to create the file, relative to project root",
|
|
16
|
+
min_length=1,
|
|
17
|
+
max_length=500,
|
|
18
|
+
)
|
|
19
|
+
content: str = Field(..., description="File content to write")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class UpdateResourceRequest(BaseModel):
|
|
23
|
+
"""Request to update an existing resource by entity ID.
|
|
24
|
+
|
|
25
|
+
Only content is required - the file path is already known from the entity.
|
|
26
|
+
Optionally can update the file_path to move the file.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
content: str = Field(..., description="File content to write")
|
|
30
|
+
file_path: str | None = Field(
|
|
31
|
+
None,
|
|
32
|
+
description="Optional new file path to move the resource",
|
|
33
|
+
min_length=1,
|
|
34
|
+
max_length=500,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ResourceResponse(BaseModel):
|
|
39
|
+
"""Response from resource operations."""
|
|
40
|
+
|
|
41
|
+
entity_id: int = Field(..., description="Internal entity ID of the resource")
|
|
42
|
+
external_id: str = Field(..., description="External UUID of the resource for API references")
|
|
43
|
+
file_path: str = Field(..., description="File path of the resource")
|
|
44
|
+
checksum: str = Field(..., description="File content checksum")
|
|
45
|
+
size: int = Field(..., description="File size in bytes")
|
|
46
|
+
created_at: float = Field(..., description="Creation timestamp")
|
|
47
|
+
modified_at: float = Field(..., description="Modification timestamp")
|
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
from .service import BaseService
|
|
4
4
|
from .file_service import FileService
|
|
5
5
|
from .entity_service import EntityService
|
|
6
|
+
from .project_service import ProjectService
|
|
6
7
|
|
|
7
|
-
__all__ = ["BaseService", "FileService", "EntityService"]
|
|
8
|
+
__all__ = ["BaseService", "FileService", "EntityService", "ProjectService"]
|