jac-scale 0.1.2__tar.gz → 0.1.3__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.
- {jac_scale-0.1.2 → jac_scale-0.1.3}/PKG-INFO +2 -2
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/abstractions/config/app_config.jac +5 -2
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/context.jac +2 -1
- jac_scale-0.1.3/jac_scale/factories/storage_factory.jac +75 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/impl/context.impl.jac +3 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/impl/serve.impl.jac +70 -9
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/memory_hierarchy.jac +3 -1
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/plugin.jac +38 -3
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/plugin_config.jac +27 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/serve.jac +3 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/targets/kubernetes/kubernetes_config.jac +9 -15
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/targets/kubernetes/kubernetes_target.jac +167 -13
- jac_scale-0.1.3/jac_scale/tests/fixtures/scale-feats/components/Button.cl.jac +32 -0
- jac_scale-0.1.3/jac_scale/tests/fixtures/scale-feats/main.jac +147 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/fixtures/test_api.jac +29 -0
- jac_scale-0.1.3/jac_scale/tests/fixtures/test_restspec.jac +37 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_deploy_k8s.py +2 -1
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_examples.py +180 -5
- jac_scale-0.1.3/jac_scale/tests/test_restspec.py +192 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_serve.py +54 -0
- jac_scale-0.1.3/jac_scale/tests/test_storage.py +274 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale.egg-info/PKG-INFO +2 -2
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale.egg-info/SOURCES.txt +6 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale.egg-info/requires.txt +1 -1
- {jac_scale-0.1.2 → jac_scale-0.1.3}/pyproject.toml +2 -2
- {jac_scale-0.1.2 → jac_scale-0.1.3}/README.md +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/__init__.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/abstractions/config/base_config.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/abstractions/database_provider.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/abstractions/deployment_target.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/abstractions/image_registry.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/abstractions/logger.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/abstractions/models/deployment_result.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/abstractions/models/resource_status.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/config_loader.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/factories/database_factory.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/factories/deployment_factory.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/factories/registry_factory.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/factories/utility_factory.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/google_sso_provider.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/impl/config_loader.impl.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/impl/memory_hierarchy.main.impl.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/impl/memory_hierarchy.mongo.impl.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/impl/memory_hierarchy.redis.impl.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/impl/user_manager.impl.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/jserver/__init__.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/jserver/impl/jfast_api.impl.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/jserver/impl/jserver.impl.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/jserver/jfast_api.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/jserver/jserver.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/providers/database/kubernetes_mongo.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/providers/database/kubernetes_redis.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/providers/registry/dockerhub.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/sso_provider.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/targets/kubernetes/utils/kubernetes_utils.impl.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/targets/kubernetes/utils/kubernetes_utils.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/__init__.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/conftest.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/fixtures/todo_app.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_abstractions.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_factories.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_file_upload.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_hooks.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_k8s_utils.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_memory_hierarchy.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/tests/test_sso.py +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/user_manager.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/utilities/loggers/standard_logger.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale/utils.jac +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale.egg-info/dependency_links.txt +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale.egg-info/entry_points.txt +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/jac_scale.egg-info/top_level.txt +0 -0
- {jac_scale-0.1.2 → jac_scale-0.1.3}/setup.cfg +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jac-scale
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Author-email: Jason Mars <jason@mars.ninja>
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: jaclang>=0.9.
|
|
7
|
+
Requires-Dist: jaclang>=0.9.12
|
|
8
8
|
Requires-Dist: python-dotenv<2.0.0,>=1.2.1
|
|
9
9
|
Requires-Dist: docker<8.0.0,>=7.1.0
|
|
10
10
|
Requires-Dist: kubernetes<35.0.0,>=34.1.0
|
|
@@ -7,7 +7,8 @@ class AppConfig {
|
|
|
7
7
|
file_name: str = 'none',
|
|
8
8
|
build: bool = False,
|
|
9
9
|
app_name: (str | None) = None,
|
|
10
|
-
testing: bool = False
|
|
10
|
+
testing: bool = False,
|
|
11
|
+
experimental: bool = False;
|
|
11
12
|
|
|
12
13
|
def init(
|
|
13
14
|
self: AppConfig,
|
|
@@ -15,13 +16,15 @@ class AppConfig {
|
|
|
15
16
|
file_name: str = 'none',
|
|
16
17
|
build: bool = False,
|
|
17
18
|
app_name: (str | None) = None,
|
|
18
|
-
testing: bool = False
|
|
19
|
+
testing: bool = False,
|
|
20
|
+
experimental: bool = False
|
|
19
21
|
) -> None {
|
|
20
22
|
self.code_folder = code_folder;
|
|
21
23
|
self.file_name = file_name;
|
|
22
24
|
self.build = build;
|
|
23
25
|
self.app_name = app_name;
|
|
24
26
|
self.testing = testing;
|
|
27
|
+
self.experimental = experimental;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
def get_code_path(self: AppConfig) -> Path {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import from contextvars { ContextVar }
|
|
1
2
|
import from dataclasses { MISSING }
|
|
2
3
|
import from typing { Any }
|
|
3
4
|
import from uuid { UUID }
|
|
4
5
|
import from jaclang.pycore.constant { Constants as Con }
|
|
5
|
-
import from jaclang.runtimelib.context { ExecutionContext }
|
|
6
|
+
import from jaclang.runtimelib.context { ExecutionContext, CallState }
|
|
6
7
|
|
|
7
8
|
"""Jac Scale Execution Context with custom memory backend.
|
|
8
9
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Factory for creating storage instances."""
|
|
2
|
+
import from typing { Any }
|
|
3
|
+
import os;
|
|
4
|
+
import from jaclang.runtimelib.storage { Storage }
|
|
5
|
+
import from jaclang.project.config { get_config }
|
|
6
|
+
|
|
7
|
+
enum StorageType {
|
|
8
|
+
LOCAL = "local"
|
|
9
|
+
# Future: S3, GCS, AZURE - add when implemented
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
"""Factory for creating storage instances.
|
|
13
|
+
|
|
14
|
+
Configuration priority: jac.toml > environment variable > default
|
|
15
|
+
|
|
16
|
+
In jac.toml:
|
|
17
|
+
[storage]
|
|
18
|
+
type = "local" # or "s3", "gcs", "azure"
|
|
19
|
+
base_path = "/data/storage"
|
|
20
|
+
create_dirs = true
|
|
21
|
+
|
|
22
|
+
Environment variables:
|
|
23
|
+
JAC_STORAGE_TYPE: Storage type (local, s3, gcs, azure)
|
|
24
|
+
JAC_STORAGE_PATH: Base directory for local storage
|
|
25
|
+
JAC_STORAGE_CREATE_DIRS: Whether to auto-create directories
|
|
26
|
+
"""
|
|
27
|
+
class StorageFactory {
|
|
28
|
+
static def create(
|
|
29
|
+
storage_type: (StorageType | str), config: (dict[str, Any] | None) = None
|
|
30
|
+
) -> Storage {
|
|
31
|
+
# Convert string to enum if needed
|
|
32
|
+
if isinstance(storage_type, str) {
|
|
33
|
+
storage_type = StorageType(storage_type);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if storage_type == StorageType.LOCAL {
|
|
37
|
+
import from jaclang.runtimelib.storage { LocalStorage }
|
|
38
|
+
cfg = config or {};
|
|
39
|
+
return LocalStorage(
|
|
40
|
+
base_path=cfg.get("base_path", "./storage"),
|
|
41
|
+
create_dirs=cfg.get("create_dirs", True)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
raise ValueError(f"Unsupported storage type: {storage_type}") ;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static def get_default(
|
|
48
|
+
base_path: str = "./storage", create_dirs: bool = True
|
|
49
|
+
) -> Storage {
|
|
50
|
+
# Get config from jac.toml if available
|
|
51
|
+
jac_config = get_config();
|
|
52
|
+
|
|
53
|
+
# Config priority: jac.toml > env var > parameter
|
|
54
|
+
if jac_config and jac_config.storage {
|
|
55
|
+
storage_type = StorageType(jac_config.storage.storage_type);
|
|
56
|
+
base_path = jac_config.storage.base_path;
|
|
57
|
+
create_dirs = jac_config.storage.create_dirs;
|
|
58
|
+
} elif os.environ.get("JAC_STORAGE_TYPE") or os.environ.get("JAC_STORAGE_PATH") {
|
|
59
|
+
storage_type_str = os.environ.get(
|
|
60
|
+
"JAC_STORAGE_TYPE", StorageType.LOCAL.value
|
|
61
|
+
);
|
|
62
|
+
storage_type = StorageType(storage_type_str);
|
|
63
|
+
base_path = os.environ.get("JAC_STORAGE_PATH", base_path);
|
|
64
|
+
create_dirs_str = os.environ.get(
|
|
65
|
+
"JAC_STORAGE_CREATE_DIRS", str(create_dirs)
|
|
66
|
+
);
|
|
67
|
+
create_dirs = create_dirs_str.lower() == "true";
|
|
68
|
+
} else {
|
|
69
|
+
storage_type = StorageType.LOCAL;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
storage_config = {"base_path": base_path, "create_dirs": create_dirs};
|
|
73
|
+
return StorageFactory.create(storage_type, storage_config);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -21,4 +21,7 @@ impl JScaleExecutionContext.init(self: JScaleExecutionContext) -> None {
|
|
|
21
21
|
# Default user_root and entry_node to system_root
|
|
22
22
|
self.user_root = self.system_root;
|
|
23
23
|
self.entry_node = self.system_root;
|
|
24
|
+
self.call_state: ContextVar[CallState] = ContextVar(
|
|
25
|
+
'call_state', default=CallState()
|
|
26
|
+
);
|
|
24
27
|
}
|
|
@@ -486,10 +486,17 @@ impl JacAPIServer.render_base_route_callback(
|
|
|
486
486
|
|
|
487
487
|
impl JacAPIServer.register_functions_endpoints -> None {
|
|
488
488
|
for func_name in self.get_functions() {
|
|
489
|
+
func_obj = self.get_functions()[func_name];
|
|
490
|
+
restspec = func_obj.restspec if func_obj?.restspec else None;
|
|
491
|
+
spec_method = restspec.method if restspec else HTTPMethod.POST;
|
|
492
|
+
spec_path = restspec.path if restspec else None;
|
|
493
|
+
|
|
494
|
+
final_path = spec_path or f"/function/{func_name}";
|
|
495
|
+
|
|
489
496
|
self.server.add_endpoint(
|
|
490
497
|
JEndPoint(
|
|
491
|
-
method=
|
|
492
|
-
path=
|
|
498
|
+
method=spec_method,
|
|
499
|
+
path=final_path,
|
|
493
500
|
callback=self.create_function_callback(func_name),
|
|
494
501
|
parameters=self.create_function_parameters(func_name),
|
|
495
502
|
response_model=None,
|
|
@@ -546,7 +553,7 @@ impl JacAPIServer.create_function_callback(
|
|
|
546
553
|
) -> Callable[..., TransportResponse] {
|
|
547
554
|
import from jaclang.runtimelib.transport { TransportResponse, Meta }
|
|
548
555
|
requires_auth = self.introspector.is_auth_required_for_function(func_name);
|
|
549
|
-
def callback(**kwargs: JsonValue) -> TransportResponse {
|
|
556
|
+
async def callback(**kwargs: JsonValue) -> TransportResponse {
|
|
550
557
|
username: (str | None) = None;
|
|
551
558
|
if requires_auth {
|
|
552
559
|
authorization = kwargs.pop('Authorization', None);
|
|
@@ -568,9 +575,21 @@ impl JacAPIServer.create_function_callback(
|
|
|
568
575
|
}
|
|
569
576
|
}
|
|
570
577
|
print(f"Executing function '{func_name}' with params: {kwargs}");
|
|
571
|
-
result = self.execution_manager.execute_function(
|
|
578
|
+
result = await self.execution_manager.execute_function(
|
|
572
579
|
self.get_functions()[func_name], kwargs, (username or '__guest__')
|
|
573
580
|
);
|
|
581
|
+
# Handle streaming responses (generators/async generators)
|
|
582
|
+
if (isgenerator(result) or isinstance(result, AsyncGenerator)) {
|
|
583
|
+
return StreamingResponse(
|
|
584
|
+
result,
|
|
585
|
+
media_type='text/event-stream',
|
|
586
|
+
headers={
|
|
587
|
+
'Cache-Control': 'no-cache',
|
|
588
|
+
'Connection': 'close',
|
|
589
|
+
'X-Accel-Buffering': 'no'
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
}
|
|
574
593
|
if 'error' in result {
|
|
575
594
|
return TransportResponse.fail(
|
|
576
595
|
code='EXECUTION_ERROR',
|
|
@@ -588,10 +607,15 @@ impl JacAPIServer.create_function_callback(
|
|
|
588
607
|
|
|
589
608
|
impl JacAPIServer.register_walkers_endpoints -> None {
|
|
590
609
|
for walker_name in self.get_walkers() {
|
|
610
|
+
walker_cls = self.get_walkers()[walker_name];
|
|
611
|
+
restspec = walker_cls.restspec if walker_cls?.restspec else None;
|
|
612
|
+
spec_method = restspec.method if restspec?.method else HTTPMethod.POST;
|
|
613
|
+
spec_path = restspec.path if restspec?.path else f"/walker/{walker_name}";
|
|
614
|
+
|
|
591
615
|
self.server.add_endpoint(
|
|
592
616
|
JEndPoint(
|
|
593
|
-
method=
|
|
594
|
-
path=f"
|
|
617
|
+
method=spec_method,
|
|
618
|
+
path=f"{spec_path}/{{node}}",
|
|
595
619
|
callback=self.create_walker_callback(walker_name, has_node_param=True),
|
|
596
620
|
parameters=self.create_walker_parameters(
|
|
597
621
|
walker_name, invoke_on_root=False
|
|
@@ -604,8 +628,8 @@ impl JacAPIServer.register_walkers_endpoints -> None {
|
|
|
604
628
|
);
|
|
605
629
|
self.server.add_endpoint(
|
|
606
630
|
JEndPoint(
|
|
607
|
-
method=
|
|
608
|
-
path=
|
|
631
|
+
method=spec_method,
|
|
632
|
+
path=spec_path,
|
|
609
633
|
callback=self.create_walker_callback(walker_name, has_node_param=False),
|
|
610
634
|
parameters=self.create_walker_parameters(
|
|
611
635
|
walker_name, invoke_on_root=True
|
|
@@ -700,6 +724,17 @@ impl JacAPIServer.create_walker_callback(
|
|
|
700
724
|
result = await self.execution_manager.spawn_walker(
|
|
701
725
|
self.get_walkers()[walker_name], kwargs, (username or '__guest__')
|
|
702
726
|
);
|
|
727
|
+
if (isgenerator(result) or isinstance(result, AsyncGenerator)) {
|
|
728
|
+
return StreamingResponse(
|
|
729
|
+
result,
|
|
730
|
+
media_type='text/event-stream',
|
|
731
|
+
headers={
|
|
732
|
+
'Cache-Control': 'no-cache',
|
|
733
|
+
'Connection': 'close',
|
|
734
|
+
'X-Accel-Buffering': 'no'
|
|
735
|
+
}
|
|
736
|
+
);
|
|
737
|
+
}
|
|
703
738
|
if 'error' in result {
|
|
704
739
|
return TransportResponse.fail(
|
|
705
740
|
code='EXECUTION_ERROR',
|
|
@@ -1260,6 +1295,20 @@ impl JacAPIServer.register_dynamic_walker_endpoint -> None {
|
|
|
1260
1295
|
result = await self.execution_manager.spawn_walker(
|
|
1261
1296
|
walkers[walker_name], kwargs, (username or '__guest__')
|
|
1262
1297
|
);
|
|
1298
|
+
|
|
1299
|
+
# Handle streaming responses (generators/async generators)
|
|
1300
|
+
if (isgenerator(result) or isinstance(result, AsyncGenerator)) {
|
|
1301
|
+
return StreamingResponse(
|
|
1302
|
+
result,
|
|
1303
|
+
media_type='text/event-stream',
|
|
1304
|
+
headers={
|
|
1305
|
+
'Cache-Control': 'no-cache',
|
|
1306
|
+
'Connection': 'close',
|
|
1307
|
+
'X-Accel-Buffering': 'no'
|
|
1308
|
+
}
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1263
1312
|
if 'error' in result {
|
|
1264
1313
|
return TransportResponse.fail(
|
|
1265
1314
|
code='EXECUTION_ERROR',
|
|
@@ -1401,9 +1450,21 @@ impl JacAPIServer.register_dynamic_function_endpoint -> None {
|
|
|
1401
1450
|
}
|
|
1402
1451
|
}
|
|
1403
1452
|
|
|
1404
|
-
result = self.execution_manager.execute_function(
|
|
1453
|
+
result = await self.execution_manager.execute_function(
|
|
1405
1454
|
functions[function_name], kwargs, (username or '__guest__')
|
|
1406
1455
|
);
|
|
1456
|
+
# Handle streaming responses (generators/async generators)
|
|
1457
|
+
if (isgenerator(result) or isinstance(result, AsyncGenerator)) {
|
|
1458
|
+
return StreamingResponse(
|
|
1459
|
+
result,
|
|
1460
|
+
media_type='text/event-stream',
|
|
1461
|
+
headers={
|
|
1462
|
+
'Cache-Control': 'no-cache',
|
|
1463
|
+
'Connection': 'close',
|
|
1464
|
+
'X-Accel-Buffering': 'no'
|
|
1465
|
+
}
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1407
1468
|
if 'error' in result {
|
|
1408
1469
|
return TransportResponse.fail(
|
|
1409
1470
|
code='EXECUTION_ERROR',
|
|
@@ -74,7 +74,9 @@ MongoDB persistence backend - implements PersistentMemory for durable L3 storage
|
|
|
74
74
|
Replaces SqliteMemory when MongoDB is available.
|
|
75
75
|
"""
|
|
76
76
|
obj MongoBackend(PersistentMemory) {
|
|
77
|
-
has client:
|
|
77
|
+
has client: MongoClient | None = None,
|
|
78
|
+
db: Any by postinit,
|
|
79
|
+
collection: Any by postinit,
|
|
78
80
|
db_name: str = 'jac_db',
|
|
79
81
|
collection_name: str = 'anchors',
|
|
80
82
|
mongo_url: str = _db_config['mongodb_uri'];
|
|
@@ -4,6 +4,7 @@ import pathlib;
|
|
|
4
4
|
import from dotenv { load_dotenv }
|
|
5
5
|
import from jaclang.cli.registry { get_registry }
|
|
6
6
|
import from jaclang.cli.command { Arg, ArgKind, CommandPriority, HookContext }
|
|
7
|
+
import from jaclang.cli.console { console }
|
|
7
8
|
import from jaclang.pycore.runtime { hookimpl, plugin_manager }
|
|
8
9
|
import from jaclang.runtimelib.context { ExecutionContext }
|
|
9
10
|
import from jaclang.runtimelib.server { JacAPIServer as JacServer }
|
|
@@ -17,6 +18,7 @@ import from .factories.utility_factory { UtilityFactory }
|
|
|
17
18
|
import from .abstractions.config.app_config { AppConfig }
|
|
18
19
|
import from .user_manager { JacScaleUserManager }
|
|
19
20
|
import from jaclang.runtimelib.server { UserManager }
|
|
21
|
+
import from jaclang.runtimelib.storage { Storage }
|
|
20
22
|
|
|
21
23
|
"""Pre-hook for jac start command to handle --scale flag."""
|
|
22
24
|
def _scale_pre_hook(context: HookContext) -> None {
|
|
@@ -25,6 +27,7 @@ def _scale_pre_hook(context: HookContext) -> None {
|
|
|
25
27
|
# Handle deployment instead of local server
|
|
26
28
|
filename = context.get_arg("filename");
|
|
27
29
|
build = context.get_arg("build", False);
|
|
30
|
+
experimental = context.get_arg("experimental", False);
|
|
28
31
|
target = context.get_arg("target", "kubernetes");
|
|
29
32
|
registry = context.get_arg("registry", "dockerhub");
|
|
30
33
|
if not os.path.exists(filename) {
|
|
@@ -59,15 +62,27 @@ def _scale_pre_hook(context: HookContext) -> None {
|
|
|
59
62
|
}
|
|
60
63
|
# Create app config
|
|
61
64
|
app_config = AppConfig(
|
|
62
|
-
code_folder=code_folder,
|
|
65
|
+
code_folder=code_folder,
|
|
66
|
+
file_name=base_file_path,
|
|
67
|
+
build=build,
|
|
68
|
+
experimental=experimental
|
|
63
69
|
);
|
|
70
|
+
if experimental {
|
|
71
|
+
console.print(
|
|
72
|
+
"Installing Jaseci packages from repository (experimental mode)..."
|
|
73
|
+
);
|
|
74
|
+
} else {
|
|
75
|
+
console.print("Installing Jaseci packages from PyPI...");
|
|
76
|
+
}
|
|
64
77
|
# Deploy
|
|
65
78
|
result = deployment_target.deploy(app_config);
|
|
66
79
|
if not result.success {
|
|
67
80
|
raise RuntimeError(result.message or "Deployment failed") ;
|
|
68
81
|
}
|
|
69
82
|
if result.service_url {
|
|
70
|
-
print(
|
|
83
|
+
console.print(
|
|
84
|
+
f"Deployment complete! Service available at: {result.service_url}"
|
|
85
|
+
);
|
|
71
86
|
}
|
|
72
87
|
# Cancel normal start execution since we handled it
|
|
73
88
|
context.set_data("cancel_execution", True);
|
|
@@ -101,6 +116,13 @@ class JacCmd {
|
|
|
101
116
|
help="Build and push Docker image (with --scale)",
|
|
102
117
|
short="b"
|
|
103
118
|
),
|
|
119
|
+
Arg.create(
|
|
120
|
+
"experimental",
|
|
121
|
+
typ=bool,
|
|
122
|
+
default=False,
|
|
123
|
+
help="Use experimental mode (install from repo instead of PyPI)",
|
|
124
|
+
short="e"
|
|
125
|
+
),
|
|
104
126
|
Arg.create(
|
|
105
127
|
"target",
|
|
106
128
|
typ=str,
|
|
@@ -168,7 +190,9 @@ class JacCmd {
|
|
|
168
190
|
app_name = os.getenv('APP_NAME') or target_config.get('app_name', 'jaseci');
|
|
169
191
|
deployment_target.destroy(app_name);
|
|
170
192
|
|
|
171
|
-
print(
|
|
193
|
+
console.print(
|
|
194
|
+
f"Successfully destroyed deployment '{app_name}' from {target}"
|
|
195
|
+
);
|
|
172
196
|
return 0;
|
|
173
197
|
}
|
|
174
198
|
}
|
|
@@ -205,6 +229,17 @@ class JacScalePlugin {
|
|
|
205
229
|
static def get_user_manager(base_path: str) -> UserManager {
|
|
206
230
|
return JacScaleUserManager(base_path=base_path);
|
|
207
231
|
}
|
|
232
|
+
|
|
233
|
+
"""Provide jac-scale's storage backend.
|
|
234
|
+
|
|
235
|
+
This overrides the core store() to use jac-scale's StorageFactory,
|
|
236
|
+
which supports cloud backends (S3, GCS, Azure) via configuration.
|
|
237
|
+
"""
|
|
238
|
+
@hookimpl
|
|
239
|
+
static def store(base_path: str = "./storage", create_dirs: bool = True) -> Storage {
|
|
240
|
+
import from .factories.storage_factory { StorageFactory }
|
|
241
|
+
return StorageFactory.get_default(base_path, create_dirs);
|
|
242
|
+
}
|
|
208
243
|
}
|
|
209
244
|
|
|
210
245
|
# Pluggy's varnames() puts parameters with defaults into kwargnames, not argnames.
|
|
@@ -149,6 +149,33 @@ class JacScalePluginConfig {
|
|
|
149
149
|
"type": "bool",
|
|
150
150
|
"default": True,
|
|
151
151
|
"description": "Enable Redis deployment in Kubernetes"
|
|
152
|
+
},
|
|
153
|
+
"plugin_versions": {
|
|
154
|
+
"type": "dict",
|
|
155
|
+
"default": {},
|
|
156
|
+
"description": "Package versions for PyPI installation (default mode). Use 'latest' or specific version.",
|
|
157
|
+
"nested": {
|
|
158
|
+
"jaclang": {
|
|
159
|
+
"type": "string",
|
|
160
|
+
"default": "latest",
|
|
161
|
+
"description": "jaclang package version"
|
|
162
|
+
},
|
|
163
|
+
"jac_scale": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"default": "latest",
|
|
166
|
+
"description": "jac-scale package version"
|
|
167
|
+
},
|
|
168
|
+
"jac_client": {
|
|
169
|
+
"type": "string",
|
|
170
|
+
"default": "latest",
|
|
171
|
+
"description": "jac-client package version"
|
|
172
|
+
},
|
|
173
|
+
"jac_byllm": {
|
|
174
|
+
"type": "string",
|
|
175
|
+
"default": "latest",
|
|
176
|
+
"description": "jac-byllm package version (use 'none' to skip)"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
152
179
|
}
|
|
153
180
|
}
|
|
154
181
|
},
|
|
@@ -24,6 +24,9 @@ import from enum { StrEnum }
|
|
|
24
24
|
import from fastapi_sso.sso.google { GoogleSSO }
|
|
25
25
|
import from jac_scale.utils { generate_random_password }
|
|
26
26
|
import from jac_scale.config_loader { get_scale_config }
|
|
27
|
+
import from typing { AsyncGenerator }
|
|
28
|
+
import from inspect { isgenerator }
|
|
29
|
+
import from fastapi.responses { StreamingResponse }
|
|
27
30
|
|
|
28
31
|
# Load configuration from jac.toml with env var overrides
|
|
29
32
|
glob _jwt_config = get_scale_config().get_jwt_config(),
|
|
@@ -34,12 +34,12 @@ class KubernetesConfig(BaseConfig) {
|
|
|
34
34
|
app_mount_path: str = '/app',
|
|
35
35
|
code_mount_path: str = '/code',
|
|
36
36
|
workspace_path: str = '/code/workspace',
|
|
37
|
-
# Runtime environment (defaults to official Jaseci repo)
|
|
38
37
|
jaseci_repo_url: str = 'https://github.com/jaseci-labs/jaseci.git',
|
|
39
38
|
jaseci_branch: str = 'main',
|
|
40
39
|
jaseci_commit: (str | None) = None,
|
|
41
40
|
install_jaseci: bool = True,
|
|
42
|
-
additional_packages: list[str] = []
|
|
41
|
+
additional_packages: list[str] = [],
|
|
42
|
+
plugin_versions: dict[str, str] = {};
|
|
43
43
|
|
|
44
44
|
def init(
|
|
45
45
|
self: KubernetesConfig,
|
|
@@ -75,12 +75,8 @@ class KubernetesConfig(BaseConfig) {
|
|
|
75
75
|
jaseci_branch: str = 'main',
|
|
76
76
|
jaseci_commit: (str | None) = None,
|
|
77
77
|
install_jaseci: bool = True,
|
|
78
|
-
additional_packages: list[str] = []
|
|
79
|
-
|
|
80
|
-
# Storage configuration
|
|
81
|
-
# Timing configuration
|
|
82
|
-
# Paths
|
|
83
|
-
# Runtime environment
|
|
78
|
+
additional_packages: list[str] = [],
|
|
79
|
+
plugin_versions: dict[str, str] = {}
|
|
84
80
|
) -> None {
|
|
85
81
|
self.app_name = app_name;
|
|
86
82
|
self.namespace = namespace;
|
|
@@ -121,6 +117,7 @@ class KubernetesConfig(BaseConfig) {
|
|
|
121
117
|
self.jaseci_commit = jaseci_commit;
|
|
122
118
|
self.install_jaseci = install_jaseci;
|
|
123
119
|
self.additional_packages = additional_packages;
|
|
120
|
+
self.plugin_versions = plugin_versions;
|
|
124
121
|
}
|
|
125
122
|
|
|
126
123
|
override def to_dict(self: KubernetesConfig) -> dict[str, Any] {
|
|
@@ -162,7 +159,8 @@ class KubernetesConfig(BaseConfig) {
|
|
|
162
159
|
'jaseci_branch': self.jaseci_branch,
|
|
163
160
|
'jaseci_commit': self.jaseci_commit,
|
|
164
161
|
'install_jaseci': self.install_jaseci,
|
|
165
|
-
'additional_packages': self.additional_packages
|
|
162
|
+
'additional_packages': self.additional_packages,
|
|
163
|
+
'plugin_versions': self.plugin_versions
|
|
166
164
|
}
|
|
167
165
|
);
|
|
168
166
|
return base;
|
|
@@ -204,12 +202,8 @@ class KubernetesConfig(BaseConfig) {
|
|
|
204
202
|
jaseci_branch=config.get('jaseci_branch', 'main'),
|
|
205
203
|
jaseci_commit=config.get('jaseci_commit'),
|
|
206
204
|
install_jaseci=config.get('install_jaseci', True),
|
|
207
|
-
additional_packages=config.get('additional_packages', [])
|
|
208
|
-
|
|
209
|
-
# Storage configuration
|
|
210
|
-
# Timing configuration
|
|
211
|
-
# Paths
|
|
212
|
-
# Runtime environment
|
|
205
|
+
additional_packages=config.get('additional_packages', []),
|
|
206
|
+
plugin_versions=config.get('plugin_versions', {})
|
|
213
207
|
);
|
|
214
208
|
}
|
|
215
209
|
}
|