clm-kernel 0.0.0__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.
- clm/__init__.py +230 -0
- clm/__main__.py +25 -0
- clm/cross_cutting/__init__.py +50 -0
- clm/cross_cutting/_test_runner.py +36 -0
- clm/cross_cutting/async_utils.py +25 -0
- clm/cross_cutting/cel_builder.py +123 -0
- clm/cross_cutting/cel_converter.py +697 -0
- clm/cross_cutting/cel_engine.py +252 -0
- clm/cross_cutting/cel_ops.py +72 -0
- clm/cross_cutting/cel_ops_db.py +157 -0
- clm/cross_cutting/cel_ops_files.py +99 -0
- clm/cross_cutting/cel_ops_state.py +71 -0
- clm/cross_cutting/cel_ops_strings.py +64 -0
- clm/cross_cutting/cel_resolver.py +63 -0
- clm/cross_cutting/cel_slices.py +56 -0
- clm/cross_cutting/cel_store.py +330 -0
- clm/cross_cutting/clm_logger.py +140 -0
- clm/cross_cutting/config/__init__.py +155 -0
- clm/cross_cutting/config/config_constants.py +392 -0
- clm/cross_cutting/config/env_parameters.py +90 -0
- clm/cross_cutting/config/logging.py +378 -0
- clm/cross_cutting/config/settings.py +504 -0
- clm/cross_cutting/context.py +5 -0
- clm/cross_cutting/domain_models.py +55 -0
- clm/cross_cutting/domain_types.py +61 -0
- clm/cross_cutting/effects.py +67 -0
- clm/cross_cutting/errors.py +153 -0
- clm/cross_cutting/governance.py +331 -0
- clm/cross_cutting/guards.py +41 -0
- clm/cross_cutting/mcard.py +321 -0
- clm/cross_cutting/native.py +185 -0
- clm/cross_cutting/observability.py +289 -0
- clm/cross_cutting/pcard.py +434 -0
- clm/cross_cutting/registry.py +71 -0
- clm/cross_cutting/resources.py +84 -0
- clm/cross_cutting/secrets.py +44 -0
- clm/cross_cutting/subprocess_utils.py +118 -0
- clm/cross_cutting/telemetry.py +164 -0
- clm/cross_cutting/testing/__init__.py +8 -0
- clm/cross_cutting/testing/comparator.py +187 -0
- clm/cross_cutting/testing/datasets.py +87 -0
- clm/cross_cutting/timeutil.py +20 -0
- clm/cross_cutting/types/new_type_check.py +0 -0
- clm/cross_cutting/utils/__init__.py +1 -0
- clm/cross_cutting/utils/url_safety.py +50 -0
- clm/cross_cutting/vcard.py +560 -0
- clm/cross_cutting/writer.py +118 -0
- clm/layer0/README.md +50 -0
- clm/layer0/__init__.py +223 -0
- clm/layer0/algebra.py +60 -0
- clm/layer0/algebra_baldwin.py +133 -0
- clm/layer0/algebra_baldwin_generators.py +36 -0
- clm/layer0/algebra_equivalence.py +262 -0
- clm/layer0/algebra_ingest.py +306 -0
- clm/layer0/algebra_manifest_io.py +156 -0
- clm/layer0/assembler.py +481 -0
- clm/layer0/cel/__init__.py +23 -0
- clm/layer0/cel_eval.py +491 -0
- clm/layer0/codec.py +106 -0
- clm/layer0/context.py +122 -0
- clm/layer0/db.py +160 -0
- clm/layer0/exceptions.py +73 -0
- clm/layer0/fibration.py +106 -0
- clm/layer0/gates.py +50 -0
- clm/layer0/hash.py +80 -0
- clm/layer0/loader.py +826 -0
- clm/layer0/math_utils.py +163 -0
- clm/layer0/mcard.py +96 -0
- clm/layer0/model/__init__.py +0 -0
- clm/layer0/model/action.py +223 -0
- clm/layer0/model/card.py +280 -0
- clm/layer0/model/card_triad.py +427 -0
- clm/layer0/model/compatibility.py +60 -0
- clm/layer0/model/dictionary.py +46 -0
- clm/layer0/model/dots.py +331 -0
- clm/layer0/model/event_producer.py +88 -0
- clm/layer0/model/g_time.py +89 -0
- clm/layer0/model/handle.py +163 -0
- clm/layer0/model/hash/__init__.py +6 -0
- clm/layer0/model/hash/algorithms/__init__.py +3 -0
- clm/layer0/model/hash/algorithms/custom_hash.py +7 -0
- clm/layer0/model/hash/algorithms/local_sha256.py +178 -0
- clm/layer0/model/hash/constants.py +53 -0
- clm/layer0/model/hash/enums.py +60 -0
- clm/layer0/model/hash/validator.py +307 -0
- clm/layer0/model/interpreter.py +275 -0
- clm/layer0/model/pagination.py +45 -0
- clm/layer0/model/pcard.py +716 -0
- clm/layer0/model/schema.py +44 -0
- clm/layer0/model/utils/__init__.py +1 -0
- clm/layer0/model/utils/content_analyzer.py +152 -0
- clm/layer0/model/validators/__init__.py +1 -0
- clm/layer0/model/validators/base_validator.py +44 -0
- clm/layer0/model/validators/binary_validator.py +66 -0
- clm/layer0/model/validators/text_validator.py +82 -0
- clm/layer0/model/validators/validation_registry.py +49 -0
- clm/layer0/model/vcard.py +823 -0
- clm/layer0/model/vcard_ext/__init__.py +39 -0
- clm/layer0/model/vcard_ext/core.py +60 -0
- clm/layer0/model/vcard_ext/network.py +23 -0
- clm/layer0/model/vcard_ext/observability.py +63 -0
- clm/layer0/model/vcard_ext/storage.py +60 -0
- clm/layer0/model/vcard_ext/vendors.py +211 -0
- clm/layer0/model/vcard_sandwich.py +119 -0
- clm/layer0/model/vcard_vocabulary.py +463 -0
- clm/layer0/model/workflow.py +274 -0
- clm/layer0/narrative.py +431 -0
- clm/layer0/ontology/collection.py +125 -0
- clm/layer0/parser.py +429 -0
- clm/layer0/relations.py +73 -0
- clm/layer0/rule_evaluator.py +251 -0
- clm/layer0/schema/__init__.py +38 -0
- clm/layer0/schema/ddl.py +97 -0
- clm/layer0/templates/abstract.yaml +99 -0
- clm/layer0/templates/balanced.yaml +253 -0
- clm/layer0/templates/concrete.yaml +172 -0
- clm/layer0/type_registry.py +223 -0
- clm/layer0/types.py +204 -0
- clm/layer0/utils.py +886 -0
- clm/layer0/verifier_core.py +262 -0
- clm/layer1/__init__.py +31 -0
- clm/layer1/action_dispatcher.py +275 -0
- clm/layer1/adapter_registry.py +233 -0
- clm/layer1/algebra_baldwin_generators.py +192 -0
- clm/layer1/arrow_compiler.py +525 -0
- clm/layer1/batch_processor.py +152 -0
- clm/layer1/cel/__init__.py +27 -0
- clm/layer1/cel/builder.py +173 -0
- clm/layer1/engine.py +759 -0
- clm/layer1/engine_async.py +89 -0
- clm/layer1/eval_callback.py +49 -0
- clm/layer1/gate_composer.py +229 -0
- clm/layer1/hoare_sandwich.py +298 -0
- clm/layer1/identity_guard.py +348 -0
- clm/layer1/matrix.py +138 -0
- clm/layer1/neural_runtime.py +221 -0
- clm/layer1/operations/__init__.py +123 -0
- clm/layer1/operations/augment.py +156 -0
- clm/layer1/operations/base.py +109 -0
- clm/layer1/operations/builtins.py +338 -0
- clm/layer1/operations/dispatch.py +144 -0
- clm/layer1/operations/exclude.py +107 -0
- clm/layer1/operations/handle.py +197 -0
- clm/layer1/operations/identity.py +139 -0
- clm/layer1/operations/invert.py +66 -0
- clm/layer1/operations/loader.py +116 -0
- clm/layer1/operations/manipulators/__init__.py +23 -0
- clm/layer1/operations/manipulators/document.py +211 -0
- clm/layer1/operations/manipulators/media.py +134 -0
- clm/layer1/operations/manipulators/structured.py +159 -0
- clm/layer1/operations/manipulators/tabular.py +334 -0
- clm/layer1/operations/port.py +65 -0
- clm/layer1/operations/services.py +529 -0
- clm/layer1/operations/split.py +117 -0
- clm/layer1/operations/substitute.py +75 -0
- clm/layer1/petri.py +1052 -0
- clm/layer1/pocketflow_orchestrator.py +408 -0
- clm/layer1/pocketflow_scheduler.py +519 -0
- clm/layer1/protocols.py +197 -0
- clm/layer1/runtime_adapter.py +718 -0
- clm/layer1/runtimes/__init__.py +71 -0
- clm/layer1/runtimes/_generated_assertions.py +125 -0
- clm/layer1/runtimes/_generated_types.py +42 -0
- clm/layer1/runtimes/base.py +265 -0
- clm/layer1/runtimes/binary.py +101 -0
- clm/layer1/runtimes/factory.py +203 -0
- clm/layer1/runtimes/javascript.py +321 -0
- clm/layer1/runtimes/javascript_runtime.js +33 -0
- clm/layer1/runtimes/js_scripts/isomorphism.mjs +22 -0
- clm/layer1/runtimes/js_scripts/loader.mjs +52 -0
- clm/layer1/runtimes/lambda_calc.py +126 -0
- clm/layer1/runtimes/python.py +288 -0
- clm/layer1/runtimes/python_runtime.py +41 -0
- clm/layer1/runtimes/script.py +114 -0
- clm/layer1/sandbox.py +334 -0
- clm/layer1/savepoint_guard.py +136 -0
- clm/layer1/sparse_net.py +122 -0
- clm/layer1/spec_tester.py +165 -0
- clm/layer1/store.py +295 -0
- clm/layer1/test_runner.py +498 -0
- clm/layer1/type_inspector.py +166 -0
- clm/layer1/verifier.py +772 -0
- clm/layer1/vm.py +91 -0
- clm/layer2/__init__.py +78 -0
- clm/layer2/card_collection.py +678 -0
- clm/layer2/classifier.py +479 -0
- clm/layer2/engine/__init__.py +1 -0
- clm/layer2/engine/abstract_sql_engine.py +320 -0
- clm/layer2/engine/base.py +193 -0
- clm/layer2/engine/duckdb_engine.py +576 -0
- clm/layer2/engine/sqlite_engine.py +518 -0
- clm/layer2/fiber/__init__.py +31 -0
- clm/layer2/fiber/context.py +89 -0
- clm/layer2/fiber/disposable.py +163 -0
- clm/layer2/fiber/fiber.py +125 -0
- clm/layer2/fiber/hoare.py +191 -0
- clm/layer2/file_io.py +376 -0
- clm/layer2/file_registrar.py +77 -0
- clm/layer2/ingest.py +202 -0
- clm/layer2/lineage.py +322 -0
- clm/layer2/mcard_fs.py +262 -0
- clm/layer2/merkle.py +11 -0
- clm/layer2/mime.py +244 -0
- clm/layer2/mime_detector.py +245 -0
- clm/layer2/private_collection.py +118 -0
- clm/layer2/shared_store.py +11 -0
- clm/layer2/storage/__init__.py +190 -0
- clm/layer2/storage/db_bitemporal.py +141 -0
- clm/layer2/storage/db_driver.py +331 -0
- clm/layer2/storage/db_hyperlinks.py +214 -0
- clm/layer2/storage/db_pool.py +139 -0
- clm/layer2/storage/db_repository.py +229 -0
- clm/layer2/storage/savepoint.py +78 -0
- clm/layer2/storage/sqlite_wal.py +74 -0
- clm/layer2/tridb.py +245 -0
- clm/layer2/vcard_receipt.py +71 -0
- clm/layer2/vfs.py +17 -0
- clm/layer3/__init__.py +141 -0
- clm/layer3/agency/__init__.py +19 -0
- clm/layer3/agency/config.py +220 -0
- clm/layer3/agency/providers/__init__.py +15 -0
- clm/layer3/agency/providers/base.py +91 -0
- clm/layer3/agency/providers/mlc_llm.py +169 -0
- clm/layer3/agency/providers/ollama.py +203 -0
- clm/layer3/agency/router.py +71 -0
- clm/layer3/agency/runtime.py +524 -0
- clm/layer3/gateway.py +353 -0
- clm/layer3/open_interpreter_adapter.py +159 -0
- clm/layer3/rag/__init__.py +70 -0
- clm/layer3/rag/cli.py +228 -0
- clm/layer3/rag/config.py +153 -0
- clm/layer3/rag/embeddings/__init__.py +16 -0
- clm/layer3/rag/embeddings/base.py +79 -0
- clm/layer3/rag/embeddings/ollama.py +211 -0
- clm/layer3/rag/embeddings/vision.py +290 -0
- clm/layer3/rag/engine.py +276 -0
- clm/layer3/rag/graph/__init__.py +22 -0
- clm/layer3/rag/graph/community.py +198 -0
- clm/layer3/rag/graph/engine.py +433 -0
- clm/layer3/rag/graph/extractor.py +255 -0
- clm/layer3/rag/graph/schema.py +115 -0
- clm/layer3/rag/graph/store.py +641 -0
- clm/layer3/rag/indexer.py +333 -0
- clm/layer3/rag/llm_providers.json +52 -0
- clm/layer3/rag/semantic_versioning.py +313 -0
- clm/layer3/rag/vector/__init__.py +28 -0
- clm/layer3/rag/vector/handle_vector_store.py +749 -0
- clm/layer3/rag/vector/schema.py +151 -0
- clm/layer3/rag/vector/store.py +632 -0
- clm/layer3/reticulum/__init__.py +55 -0
- clm/layer3/reticulum/bridge.py +74 -0
- clm/layer3/reticulum/daemon.py +88 -0
- clm/layer3/reticulum/discovery.py +164 -0
- clm/layer3/reticulum/identity.py +107 -0
- clm/layer3/reticulum/media.py +148 -0
- clm/layer3/reticulum/transport.py +133 -0
- clm/layer3/satori/__init__.py +209 -0
- clm/layer3/satori/alpha_conversion.py +168 -0
- clm/layer3/satori/beta_reduction.py +359 -0
- clm/layer3/satori/continuation.py +38 -0
- clm/layer3/satori/eta_conversion.py +205 -0
- clm/layer3/satori/free_variables.py +163 -0
- clm/layer3/satori/io_effects.py +370 -0
- clm/layer3/satori/lambda_runtime.py +726 -0
- clm/layer3/satori/lambda_term.py +230 -0
- clm/layer3/satori/sheaf_audit.py +261 -0
- clm/layer3/satori/speech_act.py +279 -0
- clm/layer4/README.md +9 -0
- clm/layer4/__init__.py +67 -0
- clm/layer4/_sovereign_executor.py +580 -0
- clm/layer4/action_commands.py +719 -0
- clm/layer4/api.py +236 -0
- clm/layer4/bootstrap/__init__.py +13 -0
- clm/layer4/bootstrap/bootstrapper.py +118 -0
- clm/layer4/bootstrap/cleanup.py +44 -0
- clm/layer4/bootstrap/clm_hooks.py +49 -0
- clm/layer4/bootstrap/genesis.py +77 -0
- clm/layer4/bootstrap/injection.py +125 -0
- clm/layer4/cli.py +549 -0
- clm/layer4/collection_manager.py +553 -0
- clm/layer4/commands/__init__.py +81 -0
- clm/layer4/commands/action_cmd.py +42 -0
- clm/layer4/commands/check_cmd.py +82 -0
- clm/layer4/commands/envelope.py +73 -0
- clm/layer4/commands/evaluate_cmd.py +224 -0
- clm/layer4/commands/mcard_cmd.py +24 -0
- clm/layer4/commands/petri_cmd.py +92 -0
- clm/layer4/commands/tridb_cmd.py +319 -0
- clm/layer4/commands/version_cmd.py +27 -0
- clm/layer4/diff_commands.py +167 -0
- clm/layer4/eoa_sponsor.py +232 -0
- clm/layer4/events.py +69 -0
- clm/layer4/flux_gateway.py +133 -0
- clm/layer4/gateway.py +91 -0
- clm/layer4/loader.py +307 -0
- clm/layer4/mcard_commands.py +166 -0
- clm/layer4/membrane.py +273 -0
- clm/layer4/navigation.py +50 -0
- clm/layer4/protocol/protocol_entry_python.py +108 -0
- clm/layer4/protocol/python_sync.py +126 -0
- clm/layer4/runner.py +150 -0
- clm/layer4/satori.py +262 -0
- clm/layer4/server/python_sync_client.py +150 -0
- clm/layer4/server/python_sync_server.py +139 -0
- clm/layer4/server/service_api.py +315 -0
- clm/layer4/server/start_servers.py +107 -0
- clm/layer4/server/stop_servers.py +24 -0
- clm/layer4/simulated_optimization_fix.py +0 -0
- clm/layer4/storage.py +463 -0
- clm/layer4/tridb_admin.py +268 -0
- clm/layer4/websocket/test_ws_client.py +104 -0
- clm/layer4/websocket/test_ws_server.py +138 -0
- clm/layer4/websocket/ws_server_local.py +160 -0
- clm/layer5/__init__.py +51 -0
- clm/layer5/async_batch_writer.py +133 -0
- clm/layer5/learning.py +276 -0
- clm/layer5/telemetry_hook.py +107 -0
- clm/layer5/type_lattice.py +238 -0
- clm/py.typed +0 -0
- clm/schemas/__init__.py +652 -0
- clm/schemas/abstract_face_schema.yaml +77 -0
- clm/schemas/cel_schema.yaml +416 -0
- clm/schemas/lifecycle/__init__.py +45 -0
- clm/schemas/lifecycle/models.py +123 -0
- clm/schemas/lifecycle/service.py +364 -0
- clm/schemas/mcard_schema.sql +192 -0
- clm/schemas/mcard_vector_schema.sql +283 -0
- clm/schemas/mlp-context-v1.json +91 -0
- clm_kernel-0.0.0.dist-info/METADATA +121 -0
- clm_kernel-0.0.0.dist-info/RECORD +333 -0
- clm_kernel-0.0.0.dist-info/WHEEL +4 -0
- clm_kernel-0.0.0.dist-info/entry_points.txt +3 -0
- clm_kernel-0.0.0.dist-info/licenses/LICENSE +21 -0
clm/layer1/protocols.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""Layer 1 Protocols: Dependency Inversion for Storage and Execution (PEP 544).
|
|
2
|
+
|
|
3
|
+
Sprint 383 (INV-383-01, DEL-383-01):
|
|
4
|
+
Defines abstract protocols for storage engines so Layer 1 execution modules
|
|
5
|
+
(PTREngine, runtimes, operations) never directly depend on Layer 2 storage
|
|
6
|
+
implementations (CardCollection).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
from typing import Any, Callable, Optional, Protocol, runtime_checkable
|
|
13
|
+
|
|
14
|
+
from clm.layer0.model.card import MCard
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@runtime_checkable
|
|
20
|
+
class CardStoreProtocol(Protocol):
|
|
21
|
+
"""Protocol defining the storage interface required by Layer 1 execution engines.
|
|
22
|
+
|
|
23
|
+
Implements the Dependency Inversion Principle: Layer 1 engines depend on
|
|
24
|
+
this abstraction, and Layer 2 CardCollection satisfies it structurally.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def get(self, hash_or_handle: str) -> Optional[MCard]:
|
|
28
|
+
"""Retrieve an MCard by content hash or handle URI."""
|
|
29
|
+
...
|
|
30
|
+
|
|
31
|
+
def add(self, card: MCard) -> str:
|
|
32
|
+
"""Add an MCard to the store and return its content hash."""
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
def add_with_handle(self, card: MCard, handle: str) -> None:
|
|
36
|
+
"""Add an MCard and associate it with a handle URI."""
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
def get_by_handle(self, handle: str) -> Optional[MCard]:
|
|
40
|
+
"""Retrieve an MCard associated with a handle URI."""
|
|
41
|
+
...
|
|
42
|
+
|
|
43
|
+
def update_handle(self, handle: str, card: MCard) -> None:
|
|
44
|
+
"""Update an existing handle URI to point to a new MCard."""
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
def get_handle_history(self, handle: str) -> list[Any]:
|
|
48
|
+
"""Retrieve the mutation history for a handle URI."""
|
|
49
|
+
...
|
|
50
|
+
|
|
51
|
+
def prune_handle_history(
|
|
52
|
+
self, handle: str, older_than: Any = None, delete_all: bool = False
|
|
53
|
+
) -> int:
|
|
54
|
+
"""Prune historical handle versions."""
|
|
55
|
+
...
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class InMemoryCardStore:
|
|
59
|
+
"""Zero-dependency, purely in-memory CardStoreProtocol implementation.
|
|
60
|
+
|
|
61
|
+
Used as the default fallback when running in hermetic Layer 1 environments
|
|
62
|
+
or under CLM_ZERO_FS=true where Layer 2 storage is not mounted.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(self, db_path: str = ":memory:") -> None:
|
|
66
|
+
self.db_path = db_path
|
|
67
|
+
self._cards: dict[str, MCard] = {}
|
|
68
|
+
self._handles: dict[str, str] = {} # handle -> current_hash
|
|
69
|
+
self._history: dict[str, list[dict[str, Any]]] = {} # handle -> list of history entries
|
|
70
|
+
|
|
71
|
+
def get(self, hash_or_handle: str) -> Optional[MCard]:
|
|
72
|
+
if hash_or_handle in self._cards:
|
|
73
|
+
return self._cards[hash_or_handle]
|
|
74
|
+
if hash_or_handle in self._handles:
|
|
75
|
+
current_hash = self._handles[hash_or_handle]
|
|
76
|
+
return self._cards.get(current_hash)
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
def add(self, card: MCard) -> str:
|
|
80
|
+
card_hash = card.hash if hasattr(card, "hash") else str(card)
|
|
81
|
+
self._cards[card_hash] = card
|
|
82
|
+
return card_hash
|
|
83
|
+
|
|
84
|
+
def add_with_handle(self, card: MCard, handle: str) -> None:
|
|
85
|
+
card_hash = self.add(card)
|
|
86
|
+
self._handles[handle] = card_hash
|
|
87
|
+
if handle not in self._history:
|
|
88
|
+
self._history[handle] = []
|
|
89
|
+
self._history[handle].append({"hash": card_hash, "action": "created"})
|
|
90
|
+
|
|
91
|
+
def get_by_handle(self, handle: str) -> Optional[MCard]:
|
|
92
|
+
current_hash = self._handles.get(handle)
|
|
93
|
+
if current_hash:
|
|
94
|
+
return self._cards.get(current_hash)
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
def update_handle(self, handle: str, card: MCard) -> None:
|
|
98
|
+
card_hash = self.add(card)
|
|
99
|
+
prev_hash = self._handles.get(handle)
|
|
100
|
+
self._handles[handle] = card_hash
|
|
101
|
+
if handle not in self._history:
|
|
102
|
+
self._history[handle] = []
|
|
103
|
+
self._history[handle].append({"previous_hash": prev_hash, "hash": card_hash, "action": "updated"})
|
|
104
|
+
|
|
105
|
+
def get_handle_history(self, handle: str) -> list[Any]:
|
|
106
|
+
return list(self._history.get(handle, []))
|
|
107
|
+
|
|
108
|
+
def prune_handle_history(
|
|
109
|
+
self, handle: str, older_than: Any = None, delete_all: bool = False
|
|
110
|
+
) -> int:
|
|
111
|
+
if handle not in self._history:
|
|
112
|
+
return 0
|
|
113
|
+
deleted = len(self._history[handle])
|
|
114
|
+
self._history[handle] = []
|
|
115
|
+
return deleted
|
|
116
|
+
|
|
117
|
+
def resolve_handle(self, handle: str) -> Optional[str]:
|
|
118
|
+
return self._handles.get(handle)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# Registry for store factory dependency injection
|
|
122
|
+
StoreFactoryFn = Callable[[Optional[str]], CardStoreProtocol]
|
|
123
|
+
_store_factory: Optional[StoreFactoryFn] = None
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def register_store_factory(factory: StoreFactoryFn) -> None:
|
|
127
|
+
"""Register a factory function for creating CardStoreProtocol instances.
|
|
128
|
+
|
|
129
|
+
Typically called by Layer 2 during module initialization.
|
|
130
|
+
"""
|
|
131
|
+
global _store_factory
|
|
132
|
+
_store_factory = factory
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def get_store_factory() -> Optional[StoreFactoryFn]:
|
|
136
|
+
"""Get the currently registered store factory, if any."""
|
|
137
|
+
return _store_factory
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def get_store(db_path: Optional[str] = None) -> CardStoreProtocol:
|
|
141
|
+
"""Create or retrieve a CardStoreProtocol instance.
|
|
142
|
+
|
|
143
|
+
Uses the registered factory (e.g. Layer 2 CardCollection) if available;
|
|
144
|
+
otherwise falls back to an InMemoryCardStore.
|
|
145
|
+
"""
|
|
146
|
+
if _store_factory is not None:
|
|
147
|
+
try:
|
|
148
|
+
return _store_factory(db_path)
|
|
149
|
+
except Exception as e:
|
|
150
|
+
logger.warning("Registered store factory failed for %s: %s; falling back to InMemoryCardStore", db_path, e)
|
|
151
|
+
|
|
152
|
+
return InMemoryCardStore(db_path=db_path or ":memory:")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# Registry for file loader dependency injection (Layer 4 -> Layer 1)
|
|
156
|
+
FileLoaderFn = Callable[..., Any]
|
|
157
|
+
_file_loader: Optional[FileLoaderFn] = None
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def register_file_loader(loader: FileLoaderFn) -> None:
|
|
161
|
+
"""Register a file loader function (typically clm.layer4.loader.load_file_to_collection)."""
|
|
162
|
+
global _file_loader
|
|
163
|
+
_file_loader = loader
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def get_file_loader() -> Optional[FileLoaderFn]:
|
|
167
|
+
"""Get the registered file loader function."""
|
|
168
|
+
return _file_loader
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# Registry for file registrar dependency injection (Layer 2 -> Layer 1)
|
|
172
|
+
FileRegistrarFn = Callable[..., Any]
|
|
173
|
+
_file_registrar_hook: Optional[FileRegistrarFn] = None
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def register_file_registrar_hook(hook: FileRegistrarFn) -> None:
|
|
177
|
+
"""Register a file registrar hook (typically clm.layer2.file_registrar.register_file_mcard_py)."""
|
|
178
|
+
global _file_registrar_hook
|
|
179
|
+
_file_registrar_hook = hook
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def get_file_registrar_hook() -> Optional[FileRegistrarFn]:
|
|
183
|
+
"""Get the registered file registrar hook."""
|
|
184
|
+
return _file_registrar_hook
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
__all__ = [
|
|
188
|
+
"CardStoreProtocol",
|
|
189
|
+
"InMemoryCardStore",
|
|
190
|
+
"register_store_factory",
|
|
191
|
+
"get_store_factory",
|
|
192
|
+
"get_store",
|
|
193
|
+
"register_file_loader",
|
|
194
|
+
"get_file_loader",
|
|
195
|
+
"register_file_registrar_hook",
|
|
196
|
+
"get_file_registrar_hook",
|
|
197
|
+
]
|