neobot-contracts 1.0.0__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.
Files changed (35) hide show
  1. neobot_contracts-1.0.0/PKG-INFO +12 -0
  2. neobot_contracts-1.0.0/README.md +3 -0
  3. neobot_contracts-1.0.0/pyproject.toml +19 -0
  4. neobot_contracts-1.0.0/pyproject.toml.orig +15 -0
  5. neobot_contracts-1.0.0/src/neobot_contracts/__init__.py +9 -0
  6. neobot_contracts-1.0.0/src/neobot_contracts/errors.py +5 -0
  7. neobot_contracts-1.0.0/src/neobot_contracts/events.py +13 -0
  8. neobot_contracts-1.0.0/src/neobot_contracts/models/__init__.py +34 -0
  9. neobot_contracts-1.0.0/src/neobot_contracts/models/base.py +38 -0
  10. neobot_contracts-1.0.0/src/neobot_contracts/models/memory.py +102 -0
  11. neobot_contracts-1.0.0/src/neobot_contracts/models/scheduled_task.py +58 -0
  12. neobot_contracts-1.0.0/src/neobot_contracts/models/trigger.py +22 -0
  13. neobot_contracts-1.0.0/src/neobot_contracts/ports/__init__.py +116 -0
  14. neobot_contracts-1.0.0/src/neobot_contracts/ports/archive_memory_access.py +220 -0
  15. neobot_contracts-1.0.0/src/neobot_contracts/ports/clock.py +22 -0
  16. neobot_contracts-1.0.0/src/neobot_contracts/ports/creator_image_access.py +62 -0
  17. neobot_contracts-1.0.0/src/neobot_contracts/ports/emoji_access.py +58 -0
  18. neobot_contracts-1.0.0/src/neobot_contracts/ports/event_source.py +27 -0
  19. neobot_contracts-1.0.0/src/neobot_contracts/ports/host.py +126 -0
  20. neobot_contracts-1.0.0/src/neobot_contracts/ports/image_analysis_access.py +41 -0
  21. neobot_contracts-1.0.0/src/neobot_contracts/ports/logging.py +30 -0
  22. neobot_contracts-1.0.0/src/neobot_contracts/ports/media_sender.py +50 -0
  23. neobot_contracts-1.0.0/src/neobot_contracts/ports/memory.py +90 -0
  24. neobot_contracts-1.0.0/src/neobot_contracts/ports/output.py +79 -0
  25. neobot_contracts-1.0.0/src/neobot_contracts/ports/plugin.py +183 -0
  26. neobot_contracts-1.0.0/src/neobot_contracts/ports/provider.py +30 -0
  27. neobot_contracts-1.0.0/src/neobot_contracts/ports/repository.py +45 -0
  28. neobot_contracts-1.0.0/src/neobot_contracts/ports/runtime_event.py +46 -0
  29. neobot_contracts-1.0.0/src/neobot_contracts/ports/sandbox.py +103 -0
  30. neobot_contracts-1.0.0/src/neobot_contracts/ports/scheduled_task_access.py +75 -0
  31. neobot_contracts-1.0.0/src/neobot_contracts/ports/screenshot.py +170 -0
  32. neobot_contracts-1.0.0/src/neobot_contracts/ports/trigger.py +28 -0
  33. neobot_contracts-1.0.0/src/neobot_contracts/ports/unit_of_work.py +39 -0
  34. neobot_contracts-1.0.0/src/neobot_contracts/py.typed +0 -0
  35. neobot_contracts-1.0.0/src/neobot_contracts/time_context.py +15 -0
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.3
2
+ Name: neobot-contracts
3
+ Version: 1.0.0
4
+ Summary: Cross-module domain models and port interfaces for NeoBot
5
+ Author: wsrsq, tangtian
6
+ Author-email: wsrsq <wsrsq001@163.com>, tangtian <a14b@126.com>
7
+ Requires-Python: >=3.13
8
+ Description-Content-Type: text/markdown
9
+
10
+ # neobot-contracts
11
+
12
+ Cross-module domain models and port interfaces for NeoBot.
@@ -0,0 +1,3 @@
1
+ # neobot-contracts
2
+
3
+ Cross-module domain models and port interfaces for NeoBot.
@@ -0,0 +1,19 @@
1
+ [project]
2
+ name = "neobot-contracts"
3
+ version = "1.0.0"
4
+ description = "Cross-module domain models and port interfaces for NeoBot"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = []
8
+
9
+ [[project.authors]]
10
+ name = "wsrsq"
11
+ email = "wsrsq001@163.com"
12
+
13
+ [[project.authors]]
14
+ name = "tangtian"
15
+ email = "a14b@126.com"
16
+
17
+ [build-system]
18
+ requires = ["uv_build>=0.9.27,<0.10.0"]
19
+ build-backend = "uv_build"
@@ -0,0 +1,15 @@
1
+ [project]
2
+ name = "neobot-contracts"
3
+ version = "1.0.0"
4
+ description = "Cross-module domain models and port interfaces for NeoBot"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "wsrsq", email = "wsrsq001@163.com" },
8
+ { name = "tangtian", email = "a14b@126.com" },
9
+ ]
10
+ requires-python = ">=3.13"
11
+ dependencies = []
12
+
13
+ [build-system]
14
+ requires = ["uv_build>=0.9.27,<0.10.0"]
15
+ build-backend = "uv_build"
@@ -0,0 +1,9 @@
1
+ """NeoBot 跨模块共享的领域模型与 Port 接口"""
2
+
3
+ from neobot_contracts.errors import NeoBotError
4
+ from neobot_contracts.events import DomainEvent
5
+
6
+ __all__ = [
7
+ "NeoBotError",
8
+ "DomainEvent",
9
+ ]
@@ -0,0 +1,5 @@
1
+ """跨模块错误基类"""
2
+
3
+
4
+ class NeoBotError(Exception):
5
+ """NeoBot 所有自定义异常的基类"""
@@ -0,0 +1,13 @@
1
+ """领域事件基类(预留)"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from datetime import datetime
7
+
8
+
9
+ @dataclass(frozen=True, slots=True)
10
+ class DomainEvent:
11
+ """所有领域事件的基类"""
12
+
13
+ occurred_at: datetime
@@ -0,0 +1,34 @@
1
+ """领域模型"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from neobot_contracts.models.base import ConversationRef, IncomingMessage, MemoryRecord
6
+ from neobot_contracts.models.memory import (
7
+ ArchiveMemory,
8
+ CreatorImageRecord,
9
+ ImageAnalysis,
10
+ TopicNode,
11
+ )
12
+ from neobot_contracts.models.scheduled_task import (
13
+ CompletedScheduledTaskRecord,
14
+ ScheduledTaskRecord,
15
+ ScheduledTaskRecurrence,
16
+ ScheduledTaskState,
17
+ )
18
+ from neobot_contracts.models.trigger import KeywordConfig, TriggerResult
19
+
20
+ __all__ = [
21
+ "ConversationRef",
22
+ "IncomingMessage",
23
+ "MemoryRecord",
24
+ "ArchiveMemory",
25
+ "CreatorImageRecord",
26
+ "ImageAnalysis",
27
+ "TopicNode",
28
+ "CompletedScheduledTaskRecord",
29
+ "ScheduledTaskRecord",
30
+ "ScheduledTaskRecurrence",
31
+ "ScheduledTaskState",
32
+ "KeywordConfig",
33
+ "TriggerResult",
34
+ ]
@@ -0,0 +1,38 @@
1
+ """基础模型"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from datetime import datetime
7
+ from typing import Any, Literal
8
+
9
+
10
+ @dataclass(frozen=True, slots=True)
11
+ class ConversationRef:
12
+ """会话引用,标识一个私聊或群聊"""
13
+
14
+ kind: Literal["private", "group"]
15
+ id: str
16
+
17
+
18
+ @dataclass(frozen=True, slots=True)
19
+ class IncomingMessage:
20
+ """从适配器接收到的消息,与协议无关的统一表示"""
21
+
22
+ event_id: str
23
+ conversation: ConversationRef
24
+ sender_id: str
25
+ sender_name: str
26
+ text: str
27
+ occurred_at: datetime
28
+ raw_payload: dict[str, Any] | None = None
29
+
30
+
31
+ @dataclass(frozen=True, slots=True)
32
+ class MemoryRecord:
33
+ """记忆条目"""
34
+
35
+ conversation: ConversationRef
36
+ speaker_id: str
37
+ content: str
38
+ created_at: datetime
@@ -0,0 +1,102 @@
1
+ """记忆模型"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from datetime import datetime
7
+ from enum import Enum
8
+
9
+
10
+ class TopicNodeType(str, Enum):
11
+ """话题节点类型"""
12
+
13
+ RAW = "raw"
14
+ SUMMARY = "summary"
15
+
16
+
17
+ @dataclass(frozen=True, slots=True)
18
+ class ArchiveMemory:
19
+ """档案式记忆"""
20
+
21
+ id: int
22
+ table_name: str # 表名,用于区分不同类别的记忆
23
+ key: str # 键名,在表内唯一标识一个条目
24
+ value: str
25
+ tags: list[str]
26
+ created_at: datetime
27
+ updated_at: datetime
28
+ version: int
29
+
30
+
31
+ @dataclass(frozen=True, slots=True)
32
+ class TopicNode:
33
+ """话题向量树节点"""
34
+
35
+ id: int
36
+ title: str
37
+ content: str
38
+ embedding: list[float]
39
+ node_type: TopicNodeType
40
+ tags: list[str]
41
+ parent_id: int | None
42
+ children_ids: list[int]
43
+ created_at: datetime
44
+
45
+
46
+ @dataclass(frozen=True, slots=True)
47
+ class ImageAnalysis:
48
+ """缓存的图片分析元数据与文本结果。"""
49
+
50
+ id: int
51
+ file_hash: str
52
+ source: str | None
53
+ mime_type: str | None
54
+ original_width: int | None
55
+ original_height: int | None
56
+ processed_width: int | None
57
+ processed_height: int | None
58
+ analysis_text: str | None
59
+ created_at: datetime
60
+ updated_at: datetime
61
+ version: int
62
+
63
+
64
+ @dataclass(frozen=True, slots=True)
65
+ class EmojiRecord:
66
+ """表情包记录 — 解析后的表情包图片元数据与描述"""
67
+
68
+ id: int
69
+ file_hash: str
70
+ file_name: str
71
+ file_path: str
72
+ mime_type: str | None
73
+ original_width: int | None
74
+ original_height: int | None
75
+ analysis_text: str | None
76
+ use_count: int
77
+ created_at: datetime
78
+ updated_at: datetime
79
+ version: int
80
+ image_source: str | None = None
81
+
82
+
83
+ @dataclass(frozen=True, slots=True)
84
+ class CreatorImageRecord:
85
+ """Creator Agent 图片元数据。"""
86
+
87
+ id: int
88
+ image_id: str
89
+ source: str
90
+ file_hash: str
91
+ file_path: str
92
+ prompt: str | None
93
+ description: str | None
94
+ mime_type: str | None
95
+ original_width: int | None
96
+ original_height: int | None
97
+ created_at: datetime
98
+ updated_at: datetime
99
+ version: int
100
+ image_source: str | None = None
101
+ #: 图库固定编号(只在入库时分配一次,不随排序/更新变化);非图库记录为 None
102
+ gallery_no: int | None = None
@@ -0,0 +1,58 @@
1
+ """定时任务领域模型。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from datetime import datetime
7
+ from enum import StrEnum
8
+ from typing import Any
9
+
10
+ from neobot_contracts.models.base import ConversationRef
11
+ from neobot_contracts.time_context import now_utc
12
+
13
+
14
+ class ScheduledTaskRecurrence(StrEnum):
15
+ ONCE = "once"
16
+ DAILY = "daily"
17
+ WEEKLY = "weekly"
18
+ MONTHLY = "monthly"
19
+ YEARLY = "yearly"
20
+
21
+
22
+ class ScheduledTaskState(StrEnum):
23
+ ACTIVE = "active"
24
+ DISABLED = "disabled"
25
+
26
+
27
+ @dataclass(frozen=True, slots=True)
28
+ class ScheduledTaskRecord:
29
+ id: int
30
+ task_uuid: str
31
+ title: str
32
+ detail: str
33
+ recurrence: ScheduledTaskRecurrence
34
+ start_at: datetime
35
+ end_at: datetime
36
+ bindings: tuple[ConversationRef, ...]
37
+ metadata: dict[str, Any] = field(default_factory=dict)
38
+ completed_window_keys: tuple[str, ...] = ()
39
+ state: ScheduledTaskState = ScheduledTaskState.ACTIVE
40
+ created_at: datetime = field(default_factory=now_utc)
41
+ updated_at: datetime = field(default_factory=now_utc)
42
+ version: int = 1
43
+
44
+
45
+ @dataclass(frozen=True, slots=True)
46
+ class CompletedScheduledTaskRecord:
47
+ id: int
48
+ task_uuid: str
49
+ title: str
50
+ detail: str
51
+ recurrence: ScheduledTaskRecurrence
52
+ start_at: datetime
53
+ end_at: datetime
54
+ bindings: tuple[ConversationRef, ...]
55
+ metadata: dict[str, Any]
56
+ completed_at: datetime
57
+ completion_reason: str
58
+ archived_payload: dict[str, Any]
@@ -0,0 +1,22 @@
1
+ """触发器模型"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+
8
+ @dataclass(frozen=True, slots=True)
9
+ class KeywordConfig:
10
+ """关键词配置"""
11
+
12
+ keyword: str
13
+ weight: float
14
+
15
+
16
+ @dataclass(frozen=True, slots=True)
17
+ class TriggerResult:
18
+ """触发结果"""
19
+
20
+ should_reply: bool
21
+ probability: float
22
+ matched_keywords: list[str]
@@ -0,0 +1,116 @@
1
+ """Port 接口集合"""
2
+
3
+ from neobot_contracts.ports.logging import Logger, NullLogger
4
+ from neobot_contracts.ports.output import CapturingOutput, NullOutput, OutputMessage, OutputPort
5
+ from neobot_contracts.ports.runtime_event import RuntimeEnvelope, RuntimeInterceptionRegistry
6
+ from neobot_contracts.ports.clock import Clock, SystemClock, now_utc
7
+ from neobot_contracts.ports.event_source import EventSource, Subscription
8
+ from neobot_contracts.ports.plugin import (
9
+ Plugin,
10
+ PluginCapability,
11
+ PluginHandle,
12
+ PluginLoader,
13
+ PluginManager,
14
+ PluginRegistry,
15
+ PluginState,
16
+ RuntimePluginContext,
17
+ )
18
+ from neobot_contracts.ports.repository import MemoryRepository, MessageRepository, ProfileRepository
19
+ from neobot_contracts.ports.provider import Provider
20
+ from neobot_contracts.ports.unit_of_work import UnitOfWork, UnitOfWorkFactory
21
+ from neobot_contracts.ports.creator_image_access import CreatorImageAccess
22
+ from neobot_contracts.ports.archive_memory_access import (
23
+ ArchiveMemoryAccess,
24
+ ArchiveMemoryAccessWrapper,
25
+ ensure_optional_str,
26
+ ensure_str,
27
+ )
28
+ from neobot_contracts.ports.image_analysis_access import ImageAnalysisAccess
29
+ from neobot_contracts.ports.host import (
30
+ CapabilityRegistry,
31
+ CapabilitySpec,
32
+ CommandRegistry,
33
+ CommandSpec,
34
+ HostRuntimeFacade,
35
+ LifecycleHooks,
36
+ QueryRegistry,
37
+ QuerySpec,
38
+ )
39
+ from neobot_contracts.ports.scheduled_task_access import ScheduledTaskAccess
40
+ from neobot_contracts.ports.sandbox import SandboxDataPort
41
+ from neobot_contracts.ports.screenshot import (
42
+ FontFace,
43
+ FontFormat,
44
+ FontLoadError,
45
+ ImageFormat,
46
+ InvalidScreenshotOptions,
47
+ RenderOptions,
48
+ ScreenshotError,
49
+ ScreenshotMode,
50
+ ScreenshotOptions,
51
+ ScreenshotPort,
52
+ ScreenshotResult,
53
+ ScreenshotTargetNotFound,
54
+ ScreenshotTimeout,
55
+ ScreenshotUnavailable,
56
+ )
57
+
58
+ __all__ = [
59
+ "Logger",
60
+ "NullLogger",
61
+ "OutputMessage",
62
+ "OutputPort",
63
+ "NullOutput",
64
+ "CapturingOutput",
65
+ "RuntimeEnvelope",
66
+ "RuntimeInterceptionRegistry",
67
+ "Clock",
68
+ "SystemClock",
69
+ "now_utc",
70
+ "EventSource",
71
+ "Subscription",
72
+ "Plugin",
73
+ "PluginCapability",
74
+ "PluginHandle",
75
+ "PluginLoader",
76
+ "PluginManager",
77
+ "PluginRegistry",
78
+ "PluginState",
79
+ "RuntimePluginContext",
80
+ "MemoryRepository",
81
+ "MessageRepository",
82
+ "ProfileRepository",
83
+ "Provider",
84
+ "UnitOfWork",
85
+ "UnitOfWorkFactory",
86
+ "CreatorImageAccess",
87
+ "ArchiveMemoryAccess",
88
+ "ArchiveMemoryAccessWrapper",
89
+ "ensure_optional_str",
90
+ "ensure_str",
91
+ "ImageAnalysisAccess",
92
+ "ScheduledTaskAccess",
93
+ "CapabilityRegistry",
94
+ "CapabilitySpec",
95
+ "CommandRegistry",
96
+ "CommandSpec",
97
+ "HostRuntimeFacade",
98
+ "LifecycleHooks",
99
+ "QueryRegistry",
100
+ "QuerySpec",
101
+ "SandboxDataPort",
102
+ "FontFace",
103
+ "FontFormat",
104
+ "FontLoadError",
105
+ "ImageFormat",
106
+ "InvalidScreenshotOptions",
107
+ "RenderOptions",
108
+ "ScreenshotError",
109
+ "ScreenshotMode",
110
+ "ScreenshotOptions",
111
+ "ScreenshotPort",
112
+ "ScreenshotResult",
113
+ "ScreenshotTargetNotFound",
114
+ "ScreenshotTimeout",
115
+ "ScreenshotUnavailable",
116
+ ]
@@ -0,0 +1,220 @@
1
+ """Archive Memory Access Port — 档案式记忆读写接口
2
+
3
+ 提供通过表名和键名获取和更新档案式记忆条目的函数接口。
4
+ 如果输入的表名或键名是 int、float、bool 等类型,会自动转换成 str。
5
+
6
+ 示例:
7
+ ```python
8
+ from neobot_contracts.ports import ArchiveMemoryAccess
9
+
10
+ class MyArchiveMemoryAccess(ArchiveMemoryAccess):
11
+ async def get(self, table_name: str, key: str):
12
+ # 实现获取逻辑
13
+ ...
14
+ # 其他方法...
15
+
16
+ # 使用包装器自动类型转换
17
+ from neobot_contracts.ports import ArchiveMemoryAccessWrapper, ensure_str
18
+
19
+ access = MyArchiveMemoryAccess()
20
+ wrapper = ArchiveMemoryAccessWrapper(access)
21
+
22
+ # 自动将整数键转换为字符串
23
+ memory = await wrapper.get("users", 123)
24
+ ```
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ from typing import TYPE_CHECKING, Optional, Protocol, runtime_checkable, Union
30
+
31
+ if TYPE_CHECKING:
32
+ from neobot_contracts.models.memory import ArchiveMemory
33
+
34
+
35
+ @runtime_checkable
36
+ class ArchiveMemoryAccess(Protocol):
37
+ """档案式记忆读写接口
38
+
39
+ 提供通过表名和键名获取和更新档案式记忆条目的功能。
40
+ 如果输入的表名或键名是 int 等类型,会自动转换成 str。
41
+ """
42
+
43
+ async def get(
44
+ self,
45
+ table_name: str,
46
+ key: str
47
+ ) -> Optional[ArchiveMemory]:
48
+ """根据表名和键名获取档案式记忆条目
49
+
50
+ Args:
51
+ table_name: 表名,用于区分不同类别的记忆
52
+ key: 键名,在表内唯一标识一个条目
53
+
54
+ Returns:
55
+ 如果找到则返回 ArchiveMemory 对象,否则返回 None
56
+ """
57
+ ...
58
+
59
+ async def set(
60
+ self,
61
+ table_name: str,
62
+ key: str,
63
+ value: str,
64
+ tags: list[str],
65
+ ) -> ArchiveMemory:
66
+ """创建或更新档案式记忆条目
67
+
68
+ 如果指定的表名和键名已存在,则更新该条目;
69
+ 如果不存在,则创建新条目。
70
+
71
+ Args:
72
+ table_name: 表名
73
+ key: 键名
74
+ value: 值
75
+ tags: 标签列表
76
+
77
+ Returns:
78
+ 创建或更新后的 ArchiveMemory 对象
79
+ """
80
+ ...
81
+
82
+ async def delete(
83
+ self,
84
+ table_name: str,
85
+ key: str,
86
+ ) -> bool:
87
+ """删除档案式记忆条目
88
+
89
+ Args:
90
+ table_name: 表名
91
+ key: 键名
92
+
93
+ Returns:
94
+ 如果成功删除返回 True,如果条目不存在返回 False
95
+ """
96
+ ...
97
+
98
+ async def exists(
99
+ self,
100
+ table_name: str,
101
+ key: str,
102
+ ) -> bool:
103
+ """检查档案式记忆条目是否存在
104
+
105
+ Args:
106
+ table_name: 表名
107
+ key: 键名
108
+
109
+ Returns:
110
+ 如果条目存在返回 True,否则返回 False
111
+ """
112
+ ...
113
+
114
+ async def list(
115
+ self,
116
+ table_name: str,
117
+ *,
118
+ tags: Optional[list[str]] = None,
119
+ key_query: Optional[str] = None,
120
+ value_query: Optional[str] = None,
121
+ limit: int = 50,
122
+ offset: int = 0,
123
+ ) -> list[ArchiveMemory]:
124
+ """按条件列出给定表的档案式记忆条目"""
125
+ ...
126
+
127
+
128
+ def ensure_str(value: Union[str, int, float, bool, None]) -> str:
129
+ """确保输入值为字符串类型
130
+
131
+ 如果输入值是 int、float、bool 等类型,会自动转换为 str。
132
+ 如果输入值是 None,会抛出 ValueError。
133
+
134
+ Args:
135
+ value: 输入值
136
+
137
+ Returns:
138
+ 字符串表示
139
+ """
140
+ if value is None:
141
+ raise ValueError("table_name and key cannot be None")
142
+ return str(value)
143
+
144
+
145
+ def ensure_optional_str(value: Union[str, int, float, bool, None]) -> Optional[str]:
146
+ """确保输入值为可选字符串类型"""
147
+ if value is None:
148
+ return None
149
+ return str(value)
150
+
151
+
152
+ class ArchiveMemoryAccessWrapper:
153
+ """ArchiveMemoryAccess 包装器,自动处理类型转换"""
154
+
155
+ def __init__(self, access: ArchiveMemoryAccess):
156
+ self._access = access
157
+
158
+ async def get(
159
+ self,
160
+ table_name: Union[str, int, float, bool, None],
161
+ key: Union[str, int, float, bool, None],
162
+ ) -> Optional[ArchiveMemory]:
163
+ """根据表名和键名获取档案式记忆条目(自动类型转换)"""
164
+ table_name_str = ensure_str(table_name)
165
+ key_str = ensure_str(key)
166
+ return await self._access.get(table_name_str, key_str)
167
+
168
+ async def set(
169
+ self,
170
+ table_name: Union[str, int, float, bool, None],
171
+ key: Union[str, int, float, bool, None],
172
+ value: str,
173
+ tags: list[str],
174
+ ) -> ArchiveMemory:
175
+ """创建或更新档案式记忆条目(自动类型转换)"""
176
+ table_name_str = ensure_str(table_name)
177
+ key_str = ensure_str(key)
178
+ return await self._access.set(table_name_str, key_str, value, tags)
179
+
180
+ async def delete(
181
+ self,
182
+ table_name: Union[str, int, float, bool, None],
183
+ key: Union[str, int, float, bool, None],
184
+ ) -> bool:
185
+ """删除档案式记忆条目(自动类型转换)"""
186
+ table_name_str = ensure_str(table_name)
187
+ key_str = ensure_str(key)
188
+ return await self._access.delete(table_name_str, key_str)
189
+
190
+ async def exists(
191
+ self,
192
+ table_name: Union[str, int, float, bool, None],
193
+ key: Union[str, int, float, bool, None],
194
+ ) -> bool:
195
+ """检查档案式记忆条目是否存在(自动类型转换)"""
196
+ table_name_str = ensure_str(table_name)
197
+ key_str = ensure_str(key)
198
+ return await self._access.exists(table_name_str, key_str)
199
+
200
+ async def list(
201
+ self,
202
+ table_name: Union[str, int, float, bool, None],
203
+ *,
204
+ tags: Optional[list[Union[str, int, float, bool, None]]] = None,
205
+ key_query: Union[str, int, float, bool, None] = None,
206
+ value_query: Union[str, int, float, bool, None] = None,
207
+ limit: int = 50,
208
+ offset: int = 0,
209
+ ) -> list[ArchiveMemory]:
210
+ """列出档案式记忆条目(自动类型转换)"""
211
+ table_name_str = ensure_str(table_name)
212
+ normalized_tags = [ensure_str(tag) for tag in tags] if tags is not None else None
213
+ return await self._access.list(
214
+ table_name_str,
215
+ tags=normalized_tags,
216
+ key_query=ensure_optional_str(key_query),
217
+ value_query=ensure_optional_str(value_query),
218
+ limit=limit,
219
+ offset=offset,
220
+ )