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
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime Factory for creating runtime executors.
|
|
3
|
+
|
|
4
|
+
This module provides the factory pattern for creating and caching
|
|
5
|
+
runtime executors based on configuration.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from .base import RUNTIME_REGISTRY, RuntimeExecutor, RuntimeType, resolve_runtime_alias
|
|
12
|
+
|
|
13
|
+
_external_executors: dict[Any, Any] = {}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def register_external_executor(runtime_key: Any, executor_or_factory: Any) -> None:
|
|
17
|
+
"""Register an external runtime executor class or factory (e.g. from Layer 3)."""
|
|
18
|
+
_external_executors[runtime_key] = executor_or_factory
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_external_executor(runtime_key: Any) -> Any:
|
|
22
|
+
"""Retrieve an externally registered runtime executor or factory."""
|
|
23
|
+
return _external_executors.get(runtime_key)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class RuntimeFactory:
|
|
27
|
+
"""Factory for creating runtime executors based on configuration."""
|
|
28
|
+
|
|
29
|
+
_executors: dict[RuntimeType, RuntimeExecutor] = {}
|
|
30
|
+
_availability_cache: dict[RuntimeType, bool] = {} # Cache for availability checks
|
|
31
|
+
_detailed_status_cache: dict[str, dict[str, Any]] | None = None
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def _get_executor_class(cls, runtime_type: RuntimeType) -> type | None:
|
|
35
|
+
"""Dynamically load the executor class from the global registry."""
|
|
36
|
+
|
|
37
|
+
if not RUNTIME_REGISTRY:
|
|
38
|
+
# Trigger module loading to populate registry if empty
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
return RUNTIME_REGISTRY.get(runtime_type.value)
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def clear_cache(cls) -> None:
|
|
45
|
+
"""Clear cached availability data. Useful for testing or env changes."""
|
|
46
|
+
cls._availability_cache.clear()
|
|
47
|
+
cls._detailed_status_cache = None
|
|
48
|
+
cls._executors.clear()
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def get_executor(cls, runtime_type: str) -> RuntimeExecutor | None:
|
|
52
|
+
"""Get or create a runtime executor for the specified type."""
|
|
53
|
+
# Handle LLM runtime specially (dynamic import to avoid circular dependency)
|
|
54
|
+
if runtime_type.lower() == "llm":
|
|
55
|
+
return cls._get_llm_executor()
|
|
56
|
+
|
|
57
|
+
# Handle Lambda runtime specially (needs CardCollection)
|
|
58
|
+
if runtime_type.lower() == "lambda":
|
|
59
|
+
return cls._get_lambda_executor()
|
|
60
|
+
|
|
61
|
+
# Resolve aliases from shared runtime_types.json (e.g., 'node' -> 'javascript')
|
|
62
|
+
runtime_type = resolve_runtime_alias(runtime_type)
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
rt_type = RuntimeType(runtime_type.lower())
|
|
66
|
+
except ValueError:
|
|
67
|
+
logging.error(f"Unsupported runtime type: {runtime_type}")
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
if rt_type not in cls._executors:
|
|
71
|
+
executor = cls._create_executor(rt_type)
|
|
72
|
+
if executor and cls._is_available(rt_type, executor):
|
|
73
|
+
cls._executors[rt_type] = executor
|
|
74
|
+
else:
|
|
75
|
+
logging.warning(f"Runtime {runtime_type} not available or invalid")
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
return cls._executors.get(rt_type)
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def _is_available(cls, rt_type: RuntimeType, executor: RuntimeExecutor) -> bool:
|
|
82
|
+
"""Check if runtime is available, using cache."""
|
|
83
|
+
if rt_type not in cls._availability_cache:
|
|
84
|
+
cls._availability_cache[rt_type] = executor.validate_environment()
|
|
85
|
+
return cls._availability_cache[rt_type]
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def _get_llm_executor(cls) -> RuntimeExecutor | None:
|
|
89
|
+
"""Get LLM executor via external registry or registered adapter (INV-383-01 / DEL-383-04)."""
|
|
90
|
+
if RuntimeType.LLM in cls._executors:
|
|
91
|
+
return cls._executors[RuntimeType.LLM]
|
|
92
|
+
|
|
93
|
+
executor_factory = _external_executors.get(RuntimeType.LLM) or _external_executors.get("llm")
|
|
94
|
+
if executor_factory is not None:
|
|
95
|
+
try:
|
|
96
|
+
executor = (
|
|
97
|
+
executor_factory()
|
|
98
|
+
if callable(executor_factory) and not isinstance(executor_factory, RuntimeExecutor)
|
|
99
|
+
else executor_factory
|
|
100
|
+
)
|
|
101
|
+
if executor and executor.validate_environment():
|
|
102
|
+
cls._executors[RuntimeType.LLM] = executor
|
|
103
|
+
return executor
|
|
104
|
+
else:
|
|
105
|
+
logging.warning("LLM runtime not available (Ollama not running?)")
|
|
106
|
+
return None
|
|
107
|
+
except Exception as e:
|
|
108
|
+
logging.error(f"Failed to instantiate LLM runtime: {e}")
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
@classmethod
|
|
114
|
+
def _get_lambda_executor(cls) -> RuntimeExecutor | None:
|
|
115
|
+
"""Get Lambda Calculus executor using CardStoreProtocol (INV-383-01)."""
|
|
116
|
+
if RuntimeType.LAMBDA in cls._executors:
|
|
117
|
+
return cls._executors[RuntimeType.LAMBDA]
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
from clm.layer1.protocols import get_store
|
|
121
|
+
|
|
122
|
+
from .lambda_calc import LambdaRuntimeExecutor
|
|
123
|
+
|
|
124
|
+
# Create an in-memory collection for Lambda terms via protocol
|
|
125
|
+
collection = get_store(":memory:")
|
|
126
|
+
executor = LambdaRuntimeExecutor(collection)
|
|
127
|
+
cls._executors[RuntimeType.LAMBDA] = executor
|
|
128
|
+
return executor
|
|
129
|
+
except Exception as e:
|
|
130
|
+
logging.error(f"Failed to import Lambda runtime: {e}")
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
@classmethod
|
|
134
|
+
def _create_executor(cls, runtime_type: RuntimeType) -> RuntimeExecutor | None:
|
|
135
|
+
"""Create a new runtime executor."""
|
|
136
|
+
# Handle LLM specially via registry
|
|
137
|
+
if runtime_type == RuntimeType.LLM:
|
|
138
|
+
executor_factory = _external_executors.get(RuntimeType.LLM) or _external_executors.get("llm")
|
|
139
|
+
if executor_factory is not None:
|
|
140
|
+
return (
|
|
141
|
+
executor_factory()
|
|
142
|
+
if callable(executor_factory) and not isinstance(executor_factory, RuntimeExecutor)
|
|
143
|
+
else executor_factory
|
|
144
|
+
)
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
executor_class = cls._get_executor_class(runtime_type)
|
|
148
|
+
return executor_class() if executor_class else None
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def list_available_runtimes(cls) -> dict[str, bool]:
|
|
152
|
+
"""List all runtime types and their availability (cached)."""
|
|
153
|
+
result = {}
|
|
154
|
+
for rt in RuntimeType:
|
|
155
|
+
if rt not in cls._availability_cache:
|
|
156
|
+
executor = cls._create_executor(rt)
|
|
157
|
+
cls._availability_cache[rt] = (
|
|
158
|
+
executor.validate_environment() if executor else False
|
|
159
|
+
)
|
|
160
|
+
result[rt.value] = cls._availability_cache[rt]
|
|
161
|
+
return result
|
|
162
|
+
|
|
163
|
+
@classmethod
|
|
164
|
+
def get_detailed_status(cls) -> dict[str, dict[str, Any]]:
|
|
165
|
+
"""Get detailed status information for all runtimes (cached)."""
|
|
166
|
+
if cls._detailed_status_cache is not None:
|
|
167
|
+
return cls._detailed_status_cache
|
|
168
|
+
|
|
169
|
+
status = {}
|
|
170
|
+
for rt in RuntimeType:
|
|
171
|
+
executor = cls._create_executor(rt)
|
|
172
|
+
status[rt.value] = (
|
|
173
|
+
executor.get_runtime_status()
|
|
174
|
+
if executor
|
|
175
|
+
else {
|
|
176
|
+
"available": False,
|
|
177
|
+
"version": None,
|
|
178
|
+
"command": rt.value,
|
|
179
|
+
"details": "Runtime executor not implemented",
|
|
180
|
+
}
|
|
181
|
+
)
|
|
182
|
+
cls._detailed_status_cache = status
|
|
183
|
+
return status
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def at_least_one_available(cls) -> bool:
|
|
187
|
+
"""Check if at least one runtime is available."""
|
|
188
|
+
return any(cls.list_available_runtimes().values())
|
|
189
|
+
|
|
190
|
+
@classmethod
|
|
191
|
+
def print_status(cls, verbose: bool = False) -> None:
|
|
192
|
+
"""Print runtime status to console."""
|
|
193
|
+
print("\n=== Polyglot Runtime Status ===")
|
|
194
|
+
for name, info in cls.get_detailed_status().items():
|
|
195
|
+
if info["available"]:
|
|
196
|
+
ver = f" {info['version']}" if info["version"] else ""
|
|
197
|
+
detail = f": {info['details']}" if verbose and info["details"] else ""
|
|
198
|
+
print(f"✓ {name.capitalize()}{ver}{detail}")
|
|
199
|
+
else:
|
|
200
|
+
print(f"✗ {name.capitalize()} not found")
|
|
201
|
+
|
|
202
|
+
available = sum(1 for i in cls.get_detailed_status().values() if i["available"])
|
|
203
|
+
print(f"{'=' * 31}\nAvailable: {available}/{len(RuntimeType)} runtimes")
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JavaScript runtime executor.
|
|
3
|
+
|
|
4
|
+
Executes JavaScript code via Node.js or Deno subprocess.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from clm.cross_cutting.config.config_constants import PTR_JAVASCRIPT_TIMEOUT_SECS
|
|
13
|
+
from clm.layer0.model.card import MCard
|
|
14
|
+
|
|
15
|
+
from ..operations import DEFAULT_OPERATIONS
|
|
16
|
+
from .base import DEFAULT_TIMEOUT, RUNTIME_CONFIG, SubprocessRuntime, register_runtime
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@register_runtime("javascript")
|
|
20
|
+
class JavaScriptRuntime(SubprocessRuntime):
|
|
21
|
+
"""JavaScript runtime executor - executes via Node.js or Deno."""
|
|
22
|
+
|
|
23
|
+
runtime_name = "JavaScript"
|
|
24
|
+
timeout = DEFAULT_TIMEOUT
|
|
25
|
+
|
|
26
|
+
def __init__(self, use_deno: bool = False):
|
|
27
|
+
super().__init__()
|
|
28
|
+
runtime_key = "deno" if use_deno else "javascript"
|
|
29
|
+
config = RUNTIME_CONFIG.get(runtime_key, RUNTIME_CONFIG.get("javascript", {}))
|
|
30
|
+
self.command = config.get("command") or "node"
|
|
31
|
+
self.eval_flag = config.get("eval_flag") or "--eval"
|
|
32
|
+
self.use_deno = use_deno
|
|
33
|
+
|
|
34
|
+
def execute(self, impl: dict[str, Any], target: MCard, ctx: dict[str, Any]) -> Any:
|
|
35
|
+
# Handle run_command builtin
|
|
36
|
+
if impl.get("builtin") == "run_command":
|
|
37
|
+
config = impl.get("config", {})
|
|
38
|
+
cmd = config.get("command")
|
|
39
|
+
if not cmd:
|
|
40
|
+
return "Error: No command provided"
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
res = subprocess.run(
|
|
44
|
+
cmd,
|
|
45
|
+
shell=True, # nosec B602
|
|
46
|
+
capture_output=True,
|
|
47
|
+
text=True,
|
|
48
|
+
timeout=self.timeout,
|
|
49
|
+
)
|
|
50
|
+
if res.returncode != 0:
|
|
51
|
+
return f"Error: Command failed: {res.stderr}"
|
|
52
|
+
return res.stdout.strip()
|
|
53
|
+
except (OSError, subprocess.SubprocessError) as e:
|
|
54
|
+
return f"Error executing command: {e}"
|
|
55
|
+
|
|
56
|
+
# Handle loader builtin via Node.js
|
|
57
|
+
if impl.get("builtin") == "loader":
|
|
58
|
+
return self._execute_loader_builtin(impl, ctx)
|
|
59
|
+
|
|
60
|
+
# Handle isomorphism builtins via Node.js
|
|
61
|
+
if impl.get("builtin") in (
|
|
62
|
+
"isomorphism_pre",
|
|
63
|
+
"isomorphism_transition",
|
|
64
|
+
"isomorphism_post",
|
|
65
|
+
):
|
|
66
|
+
return self._execute_isomorphism_builtin(impl, ctx)
|
|
67
|
+
|
|
68
|
+
# Handle static_server builtin
|
|
69
|
+
# Reuse shared Python implementation for consistency
|
|
70
|
+
if impl.get("builtin") == "static_server":
|
|
71
|
+
return DEFAULT_OPERATIONS["static_server"](impl, target, ctx)
|
|
72
|
+
|
|
73
|
+
if impl.get("process") == "invoke_library":
|
|
74
|
+
module_name = impl.get("module")
|
|
75
|
+
func_name = impl.get("function")
|
|
76
|
+
if not func_name:
|
|
77
|
+
return "Error: No function specified in invoke_library"
|
|
78
|
+
|
|
79
|
+
code = f"""
|
|
80
|
+
let mod = globalThis;
|
|
81
|
+
const modName = "{module_name or ''}";
|
|
82
|
+
if (modName && modName !== "None") {{
|
|
83
|
+
mod = await import(modName);
|
|
84
|
+
if (mod.default && typeof mod["{func_name}"] === 'undefined') {{
|
|
85
|
+
mod = mod.default;
|
|
86
|
+
}}
|
|
87
|
+
}}
|
|
88
|
+
let func = mod;
|
|
89
|
+
for (const part of "{func_name}".split('.')) {{
|
|
90
|
+
func = func[part];
|
|
91
|
+
}}
|
|
92
|
+
|
|
93
|
+
if (!func || typeof func !== 'function') {{
|
|
94
|
+
throw new Error(`Function {func_name} not found in ${{modName || 'globalThis'}}`);
|
|
95
|
+
}}
|
|
96
|
+
|
|
97
|
+
const inputs_def = {json.dumps(impl.get("inputs", {}))};
|
|
98
|
+
let args = [];
|
|
99
|
+
let input_keys = Array.isArray(inputs_def) ? inputs_def : Object.keys(inputs_def || {{}});
|
|
100
|
+
|
|
101
|
+
if (input_keys.length === 0) {{
|
|
102
|
+
let val = target;
|
|
103
|
+
if (!isNaN(val) && String(val).trim() !== '') val = Number(val);
|
|
104
|
+
args.push(val);
|
|
105
|
+
}} else {{
|
|
106
|
+
for (let key of input_keys) {{
|
|
107
|
+
let val = context[key];
|
|
108
|
+
if (val === undefined && key === 'target') {{
|
|
109
|
+
val = target;
|
|
110
|
+
if (!isNaN(val) && String(val).trim() !== '') val = Number(val);
|
|
111
|
+
}}
|
|
112
|
+
args.push(val);
|
|
113
|
+
}}
|
|
114
|
+
}}
|
|
115
|
+
|
|
116
|
+
result = await func(...args);
|
|
117
|
+
"""
|
|
118
|
+
else:
|
|
119
|
+
code = impl.get("code", "")
|
|
120
|
+
if not code and not impl.get("entry_point", {}).get("file"):
|
|
121
|
+
return "Error: No JavaScript code or file provided"
|
|
122
|
+
|
|
123
|
+
input_data = {
|
|
124
|
+
"target": target.get_content().decode("utf-8", errors="ignore"),
|
|
125
|
+
"context": ctx,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# Safe serialization function to handle Python native objects passed from pyCubed
|
|
129
|
+
def safe_serialize(obj):
|
|
130
|
+
if callable(obj) or hasattr(obj, "__class__"):
|
|
131
|
+
return str(obj)
|
|
132
|
+
raise TypeError(f"Type {type(obj)} not serializable")
|
|
133
|
+
|
|
134
|
+
# Use IIFE pattern to isolate user code's variable declarations
|
|
135
|
+
# User code can use 'var result', 'let result', or 'const result'
|
|
136
|
+
# The wrapper captures 'result' from the user's scope
|
|
137
|
+
js_code = f"""
|
|
138
|
+
(async () => {{
|
|
139
|
+
const __input__ = {json.dumps(input_data, default=safe_serialize)};
|
|
140
|
+
const target = __input__.target;
|
|
141
|
+
const context = __input__.context;
|
|
142
|
+
let __result__;
|
|
143
|
+
try {{
|
|
144
|
+
// Execute user code in IIFE to capture 'result'
|
|
145
|
+
__result__ = (() => {{
|
|
146
|
+
{code}
|
|
147
|
+
return (typeof result !== 'undefined') ? result : undefined;
|
|
148
|
+
}})();
|
|
149
|
+
}} catch (e) {{
|
|
150
|
+
__result__ = {{ error: e.message, stack: e.stack }};
|
|
151
|
+
process.exitCode = 1;
|
|
152
|
+
}}
|
|
153
|
+
console.log(JSON.stringify(__result__));
|
|
154
|
+
}})();
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
cmd = self.command
|
|
159
|
+
if isinstance(cmd, str):
|
|
160
|
+
cmd_list = [cmd]
|
|
161
|
+
else:
|
|
162
|
+
cmd_list = list(cmd)
|
|
163
|
+
|
|
164
|
+
env = os.environ.copy()
|
|
165
|
+
env["NODE_OPTIONS"] = "--experimental-wasm-modules"
|
|
166
|
+
|
|
167
|
+
result = subprocess.run(
|
|
168
|
+
cmd_list + [self.eval_flag, js_code], # nosec B603
|
|
169
|
+
capture_output=True,
|
|
170
|
+
text=True,
|
|
171
|
+
timeout=self.timeout,
|
|
172
|
+
env=env,
|
|
173
|
+
)
|
|
174
|
+
if result.returncode != 0:
|
|
175
|
+
return f"Error: JavaScript execution failed: {result.stderr}"
|
|
176
|
+
output = result.stdout.strip()
|
|
177
|
+
if not output:
|
|
178
|
+
return None
|
|
179
|
+
return json.loads(output)
|
|
180
|
+
except subprocess.TimeoutExpired:
|
|
181
|
+
return "Error: JavaScript execution timed out"
|
|
182
|
+
except json.JSONDecodeError as e:
|
|
183
|
+
# If JSON parsing fails, return the raw output
|
|
184
|
+
return (
|
|
185
|
+
result.stdout.strip()
|
|
186
|
+
if result.stdout
|
|
187
|
+
else f"Error: Invalid JSON output: {e}"
|
|
188
|
+
)
|
|
189
|
+
except (OSError, subprocess.SubprocessError) as e:
|
|
190
|
+
return f"Error executing JavaScript: {e}"
|
|
191
|
+
|
|
192
|
+
def _execute_loader_builtin(self, impl: dict[str, Any], ctx: dict[str, Any]) -> Any:
|
|
193
|
+
"""Execute JS loader builtin via Node.js using mcard-js."""
|
|
194
|
+
# Get parameters
|
|
195
|
+
input_args = impl.get("input_arguments", {})
|
|
196
|
+
source_dir = input_args.get("source_dir") or ctx.get("source_dir", "docs")
|
|
197
|
+
db_path = input_args.get("db_path") or ctx.get("db_path", "data/loader_js.db")
|
|
198
|
+
recursive = input_args.get("recursive", True)
|
|
199
|
+
|
|
200
|
+
# Find paths
|
|
201
|
+
import pathlib
|
|
202
|
+
|
|
203
|
+
module_dir = pathlib.Path(__file__).resolve().parent
|
|
204
|
+
project_root = module_dir.parents[3]
|
|
205
|
+
mcard_js_path = project_root / "mcard-js"
|
|
206
|
+
script_path = module_dir / "js_scripts" / "loader.mjs"
|
|
207
|
+
|
|
208
|
+
try:
|
|
209
|
+
env = os.environ.copy()
|
|
210
|
+
env["NODE_OPTIONS"] = "--experimental-wasm-modules"
|
|
211
|
+
|
|
212
|
+
result = subprocess.run(
|
|
213
|
+
[
|
|
214
|
+
"npx",
|
|
215
|
+
"tsx",
|
|
216
|
+
str(script_path),
|
|
217
|
+
str(source_dir),
|
|
218
|
+
str(db_path),
|
|
219
|
+
str(project_root),
|
|
220
|
+
str(recursive).lower(),
|
|
221
|
+
], # nosec B603, B607
|
|
222
|
+
capture_output=True,
|
|
223
|
+
text=True,
|
|
224
|
+
timeout=PTR_JAVASCRIPT_TIMEOUT_SECS,
|
|
225
|
+
cwd=str(mcard_js_path),
|
|
226
|
+
env=env,
|
|
227
|
+
)
|
|
228
|
+
if result.returncode != 0:
|
|
229
|
+
stderr = result.stderr or ""
|
|
230
|
+
return {"success": False, "error": f"JS loader failed: {stderr}"}
|
|
231
|
+
try:
|
|
232
|
+
# Parse last line that contains JSON (skip debug output)
|
|
233
|
+
stdout = result.stdout.strip()
|
|
234
|
+
lines = stdout.split("\n")
|
|
235
|
+
for line in reversed(lines):
|
|
236
|
+
line = line.strip()
|
|
237
|
+
if line.startswith("{") and line.endswith("}"):
|
|
238
|
+
return json.loads(line)
|
|
239
|
+
return {
|
|
240
|
+
"success": False,
|
|
241
|
+
"error": f"No JSON found in output. Stdout: {stdout[:200]}",
|
|
242
|
+
}
|
|
243
|
+
except json.JSONDecodeError as e:
|
|
244
|
+
return {
|
|
245
|
+
"success": False,
|
|
246
|
+
"error": f"JSON parse error: {e}. Stdout: {result.stdout[:500]}",
|
|
247
|
+
}
|
|
248
|
+
except subprocess.TimeoutExpired:
|
|
249
|
+
return {"success": False, "error": "JS loader timed out"}
|
|
250
|
+
except (OSError, subprocess.SubprocessError) as e:
|
|
251
|
+
return {"success": False, "error": str(e)}
|
|
252
|
+
|
|
253
|
+
def _execute_isomorphism_builtin(
|
|
254
|
+
self, impl: dict[str, Any], ctx: dict[str, Any]
|
|
255
|
+
) -> Any:
|
|
256
|
+
"""Execute JS isomorphism builtins via Node.js using mcard-js."""
|
|
257
|
+
builtin_type = impl.get("builtin")
|
|
258
|
+
input_args = impl.get("input_arguments", {})
|
|
259
|
+
|
|
260
|
+
import pathlib
|
|
261
|
+
|
|
262
|
+
module_dir = pathlib.Path(__file__).resolve().parent
|
|
263
|
+
project_root = module_dir.parents[3]
|
|
264
|
+
mcard_js_path = project_root / "mcard-js"
|
|
265
|
+
script_path = module_dir / "js_scripts" / "isomorphism.mjs"
|
|
266
|
+
|
|
267
|
+
source_dir = input_args.get("source_dir") or ctx.get("source_dir", "")
|
|
268
|
+
db_path = input_args.get("db_path") or ctx.get("db_path", "")
|
|
269
|
+
dest_dir = input_args.get("dest_dir") or ctx.get("dest_dir", "")
|
|
270
|
+
source_hashes = input_args.get("source_hashes", {})
|
|
271
|
+
|
|
272
|
+
js_data = json.dumps(
|
|
273
|
+
{
|
|
274
|
+
"source_dir": source_dir,
|
|
275
|
+
"db_path": db_path,
|
|
276
|
+
"dest_dir": dest_dir,
|
|
277
|
+
"source_hashes": source_hashes,
|
|
278
|
+
}
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
try:
|
|
282
|
+
env = os.environ.copy()
|
|
283
|
+
env["NODE_OPTIONS"] = "--experimental-wasm-modules"
|
|
284
|
+
|
|
285
|
+
result = subprocess.run(
|
|
286
|
+
[
|
|
287
|
+
"npx",
|
|
288
|
+
"tsx",
|
|
289
|
+
str(script_path),
|
|
290
|
+
str(builtin_type),
|
|
291
|
+
js_data,
|
|
292
|
+
], # nosec B603, B607
|
|
293
|
+
capture_output=True,
|
|
294
|
+
text=True,
|
|
295
|
+
timeout=PTR_JAVASCRIPT_TIMEOUT_SECS,
|
|
296
|
+
cwd=str(mcard_js_path),
|
|
297
|
+
env=env,
|
|
298
|
+
)
|
|
299
|
+
if result.returncode != 0:
|
|
300
|
+
stderr = result.stderr or ""
|
|
301
|
+
return {"success": False, "error": f"JS isomorphism failed: {stderr}"}
|
|
302
|
+
try:
|
|
303
|
+
stdout = result.stdout.strip()
|
|
304
|
+
lines = stdout.split("\n")
|
|
305
|
+
for line in reversed(lines):
|
|
306
|
+
line = line.strip()
|
|
307
|
+
if line.startswith("{") and line.endswith("}"):
|
|
308
|
+
return json.loads(line)
|
|
309
|
+
return {
|
|
310
|
+
"success": False,
|
|
311
|
+
"error": f"No JSON found. Stdout: {stdout[:200]}",
|
|
312
|
+
}
|
|
313
|
+
except json.JSONDecodeError as e:
|
|
314
|
+
return {
|
|
315
|
+
"success": False,
|
|
316
|
+
"error": f"JSON parse error: {e}. Stdout: {result.stdout[:500]}",
|
|
317
|
+
}
|
|
318
|
+
except subprocess.TimeoutExpired:
|
|
319
|
+
return {"success": False, "error": "JS isomorphism timed out"}
|
|
320
|
+
except (OSError, subprocess.SubprocessError) as e:
|
|
321
|
+
return {"success": False, "error": str(e)}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JavaScript Native Sandbox Evaluator
|
|
3
|
+
*
|
|
4
|
+
* Invoked by the Meta Circular Evaluator to execute Javascript dynamically natively.
|
|
5
|
+
* Input format expects { target: "string", context: { ... } } pushed in payload.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
|
|
10
|
+
(async () => {
|
|
11
|
+
try {
|
|
12
|
+
// Assume STDIN provides the execution payload.
|
|
13
|
+
const inputData = fs.readFileSync(0, 'utf-8');
|
|
14
|
+
const __input__ = JSON.parse(inputData);
|
|
15
|
+
|
|
16
|
+
const target = __input__.target;
|
|
17
|
+
const context = __input__.context;
|
|
18
|
+
const code = __input__.code;
|
|
19
|
+
|
|
20
|
+
let __result__;
|
|
21
|
+
|
|
22
|
+
// Execute user code in IIFE to capture 'result' globally securely
|
|
23
|
+
__result__ = (() => {
|
|
24
|
+
eval(code);
|
|
25
|
+
return (typeof result !== 'undefined') ? result : undefined;
|
|
26
|
+
})();
|
|
27
|
+
|
|
28
|
+
console.log(JSON.stringify(__result__));
|
|
29
|
+
} catch (e) {
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
console.log(JSON.stringify({ error: e.message, stack: e.stack }));
|
|
32
|
+
}
|
|
33
|
+
})();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { executeIsomorphismPre, executeIsomorphismTransition, executeIsomorphismPost } from './src/ptr/node/core/operations/isomorphism.js';
|
|
2
|
+
|
|
3
|
+
const builtin_type = process.argv[2];
|
|
4
|
+
const data = JSON.parse(process.argv[3]);
|
|
5
|
+
|
|
6
|
+
(async () => {
|
|
7
|
+
let result;
|
|
8
|
+
try {
|
|
9
|
+
if (builtin_type === 'isomorphism_pre') {
|
|
10
|
+
result = await executeIsomorphismPre(data);
|
|
11
|
+
} else if (builtin_type === 'isomorphism_transition') {
|
|
12
|
+
result = await executeIsomorphismTransition(data);
|
|
13
|
+
} else if (builtin_type === 'isomorphism_post') {
|
|
14
|
+
result = await executeIsomorphismPost(data);
|
|
15
|
+
}
|
|
16
|
+
console.log(JSON.stringify(result));
|
|
17
|
+
process.exit(0);
|
|
18
|
+
} catch (err) {
|
|
19
|
+
console.error(JSON.stringify({ success: false, error: err.message }));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
})();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SqliteNodeEngine } from './src/storage/SqliteNodeEngine.js';
|
|
2
|
+
import { CardCollection } from './src/model/CardCollection.js';
|
|
3
|
+
import { loadFileToCollection } from './src/Loader.js';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
|
|
7
|
+
const sourceDir = process.argv[2];
|
|
8
|
+
const dbPath = process.argv[3];
|
|
9
|
+
const projectRoot = process.argv[4];
|
|
10
|
+
const recursive = process.argv[5] === 'true';
|
|
11
|
+
|
|
12
|
+
const sourcePath = path.isAbsolute(sourceDir) ? sourceDir : path.join(projectRoot, sourceDir);
|
|
13
|
+
const resolvedDbPath = path.isAbsolute(dbPath) ? dbPath : path.join(projectRoot, dbPath);
|
|
14
|
+
|
|
15
|
+
// Ensure directory
|
|
16
|
+
const dbDir = path.dirname(resolvedDbPath);
|
|
17
|
+
if (!fs.existsSync(dbDir)) fs.mkdirSync(dbDir, { recursive: true });
|
|
18
|
+
|
|
19
|
+
// Remove existing DB and WAL/SHM files
|
|
20
|
+
if (fs.existsSync(resolvedDbPath)) fs.unlinkSync(resolvedDbPath);
|
|
21
|
+
const walPath = resolvedDbPath + '-wal';
|
|
22
|
+
const shmPath = resolvedDbPath + '-shm';
|
|
23
|
+
if (fs.existsSync(walPath)) fs.unlinkSync(walPath);
|
|
24
|
+
if (fs.existsSync(shmPath)) fs.unlinkSync(shmPath);
|
|
25
|
+
|
|
26
|
+
(async () => {
|
|
27
|
+
try {
|
|
28
|
+
const engine = await SqliteNodeEngine.create(resolvedDbPath);
|
|
29
|
+
const collection = new CardCollection(engine);
|
|
30
|
+
|
|
31
|
+
const result = await loadFileToCollection(sourcePath, collection, { recursive, includeProblematic: false });
|
|
32
|
+
console.log(JSON.stringify({
|
|
33
|
+
success: true,
|
|
34
|
+
metrics: {
|
|
35
|
+
total_files: result.metrics.filesCount,
|
|
36
|
+
total_directories: result.metrics.directoriesCount,
|
|
37
|
+
directory_levels: result.metrics.directoryLevels,
|
|
38
|
+
total_size_bytes: result.results.reduce((a, r) => a + (r.size || 0), 0)
|
|
39
|
+
},
|
|
40
|
+
files: result.results.slice(0, 10).map(r => ({
|
|
41
|
+
hash: r.hash.substring(0, 8),
|
|
42
|
+
filename: r.filename,
|
|
43
|
+
content_type: r.contentType
|
|
44
|
+
}))
|
|
45
|
+
}));
|
|
46
|
+
await engine.close();
|
|
47
|
+
process.exit(0);
|
|
48
|
+
} catch (err) {
|
|
49
|
+
console.error(JSON.stringify({ success: false, error: err.message }));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
})();
|