digitalkin 0.3.0rc1__py3-none-any.whl → 0.3.1__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.
Files changed (43) hide show
  1. digitalkin/__version__.py +1 -1
  2. digitalkin/core/common/__init__.py +9 -0
  3. digitalkin/core/common/factories.py +156 -0
  4. digitalkin/core/job_manager/base_job_manager.py +128 -28
  5. digitalkin/core/job_manager/single_job_manager.py +80 -25
  6. digitalkin/core/job_manager/taskiq_broker.py +114 -19
  7. digitalkin/core/job_manager/taskiq_job_manager.py +291 -39
  8. digitalkin/core/task_manager/base_task_manager.py +539 -0
  9. digitalkin/core/task_manager/local_task_manager.py +108 -0
  10. digitalkin/core/task_manager/remote_task_manager.py +87 -0
  11. digitalkin/core/task_manager/surrealdb_repository.py +43 -4
  12. digitalkin/core/task_manager/task_executor.py +249 -0
  13. digitalkin/core/task_manager/task_session.py +107 -19
  14. digitalkin/grpc_servers/module_server.py +2 -2
  15. digitalkin/grpc_servers/module_servicer.py +21 -12
  16. digitalkin/grpc_servers/registry_server.py +1 -1
  17. digitalkin/grpc_servers/registry_servicer.py +4 -4
  18. digitalkin/grpc_servers/utils/grpc_error_handler.py +53 -0
  19. digitalkin/models/core/task_monitor.py +17 -0
  20. digitalkin/models/grpc_servers/models.py +4 -4
  21. digitalkin/models/module/module_context.py +5 -0
  22. digitalkin/models/module/module_types.py +304 -16
  23. digitalkin/modules/_base_module.py +66 -28
  24. digitalkin/services/cost/grpc_cost.py +8 -41
  25. digitalkin/services/filesystem/grpc_filesystem.py +9 -38
  26. digitalkin/services/services_config.py +11 -0
  27. digitalkin/services/services_models.py +3 -1
  28. digitalkin/services/setup/default_setup.py +5 -6
  29. digitalkin/services/setup/grpc_setup.py +51 -14
  30. digitalkin/services/storage/grpc_storage.py +2 -2
  31. digitalkin/services/user_profile/__init__.py +12 -0
  32. digitalkin/services/user_profile/default_user_profile.py +55 -0
  33. digitalkin/services/user_profile/grpc_user_profile.py +69 -0
  34. digitalkin/services/user_profile/user_profile_strategy.py +40 -0
  35. digitalkin/utils/__init__.py +28 -0
  36. digitalkin/utils/dynamic_schema.py +483 -0
  37. {digitalkin-0.3.0rc1.dist-info → digitalkin-0.3.1.dist-info}/METADATA +9 -29
  38. {digitalkin-0.3.0rc1.dist-info → digitalkin-0.3.1.dist-info}/RECORD +42 -30
  39. modules/dynamic_setup_module.py +362 -0
  40. digitalkin/core/task_manager/task_manager.py +0 -439
  41. {digitalkin-0.3.0rc1.dist-info → digitalkin-0.3.1.dist-info}/WHEEL +0 -0
  42. {digitalkin-0.3.0rc1.dist-info → digitalkin-0.3.1.dist-info}/licenses/LICENSE +0 -0
  43. {digitalkin-0.3.0rc1.dist-info → digitalkin-0.3.1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.3.0rc1
3
+ Version: 0.3.1
4
4
  Summary: SDK to build kin used in DigitalKin
5
5
  Author-email: "DigitalKin.ai" <contact@digitalkin.ai>
6
6
  License: Attribution-NonCommercial-ShareAlike 4.0 International
@@ -452,37 +452,17 @@ Classifier: License :: Other/Proprietary License
452
452
  Requires-Python: >=3.10
453
453
  Description-Content-Type: text/markdown
454
454
  License-File: LICENSE
455
- Requires-Dist: digitalkin-proto>=0.1.16
456
- Requires-Dist: grpcio-health-checking>=1.71.0
457
- Requires-Dist: grpcio-reflection>=1.71.0
458
- Requires-Dist: grpcio-status>=1.71.0
459
- Requires-Dist: pydantic>=2.12.1
455
+ Requires-Dist: digitalkin-proto==0.2.0
456
+ Requires-Dist: grpcio-health-checking>=1.76.0
457
+ Requires-Dist: grpcio-reflection>=1.76.0
458
+ Requires-Dist: grpcio-status>=1.76.0
459
+ Requires-Dist: pydantic>=2.12.5
460
460
  Requires-Dist: surrealdb>=1.0.6
461
461
  Provides-Extra: taskiq
462
- Requires-Dist: rstream>=0.31.0; extra == "taskiq"
463
- Requires-Dist: taskiq-aio-pika>=0.4.3; extra == "taskiq"
462
+ Requires-Dist: rstream>=0.40.0; extra == "taskiq"
463
+ Requires-Dist: taskiq-aio-pika>=0.5.0; extra == "taskiq"
464
464
  Requires-Dist: taskiq-redis>=1.1.2; extra == "taskiq"
465
- Requires-Dist: taskiq[reload]>=0.11.18; extra == "taskiq"
466
- Provides-Extra: dev
467
- Requires-Dist: typos>=1.38.0; extra == "dev"
468
- Requires-Dist: ruff>=0.14.1; extra == "dev"
469
- Requires-Dist: mypy>=1.18.2; extra == "dev"
470
- Requires-Dist: pyright>=1.1.406; extra == "dev"
471
- Requires-Dist: pre-commit>=4.3.0; extra == "dev"
472
- Requires-Dist: bump-my-version>=1.2.4; extra == "dev"
473
- Requires-Dist: build>=1.3.0; extra == "dev"
474
- Requires-Dist: twine>=6.2.0; extra == "dev"
475
- Requires-Dist: cryptography>=46.0.2; extra == "dev"
476
- Provides-Extra: tests
477
- Requires-Dist: freezegun>=1.5.3; extra == "tests"
478
- Requires-Dist: hdrhistogram>=0.10.3; extra == "tests"
479
- Requires-Dist: grpcio-testing>=1.71.0; extra == "tests"
480
- Requires-Dist: psutil>=7.0.0; extra == "tests"
481
- Requires-Dist: pytest>=8.4.2; extra == "tests"
482
- Requires-Dist: pytest-asyncio>=1.2.0; extra == "tests"
483
- Requires-Dist: pytest-cov>=7.0.0; extra == "tests"
484
- Requires-Dist: pytest-html==4.1.1; extra == "tests"
485
- Requires-Dist: pytest-json-report==1.5.0; extra == "tests"
465
+ Requires-Dist: taskiq[reload]>=0.12.0; extra == "taskiq"
486
466
  Dynamic: license-file
487
467
 
488
468
  # DigitalKin Python SDK
@@ -7,28 +7,34 @@ base_server/mock/__init__.py,sha256=YZFT-F1l_TpvJYuIPX-7kTeE1CfOjhx9YmNRXVoi-jQ,
7
7
  base_server/mock/mock_pb2.py,sha256=sETakcS3PAAm4E-hTCV1jIVaQTPEAIoVVHupB8Z_k7Y,1843
8
8
  base_server/mock/mock_pb2_grpc.py,sha256=BbOT70H6q3laKgkHfOx1QdfmCS_HxCY4wCOX84YAdG4,3180
9
9
  digitalkin/__init__.py,sha256=7LLBAba0th-3SGqcpqFO-lopWdUkVLKzLZiMtB-mW3M,162
10
- digitalkin/__version__.py,sha256=R-V9kMfZiYqI-Y5MJxvvyFY9miiXM4kkiJl2gmUyr1E,194
10
+ digitalkin/__version__.py,sha256=0omxzqFcYfxaU-TVHe1JXWxx_WF4A1CqJ5Rn6pCDm30,190
11
11
  digitalkin/logger.py,sha256=8ze_tjt2G6mDTuQcsf7-UTXWP3UHZ7LZVSs_iqF4rX4,4685
12
12
  digitalkin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  digitalkin/core/__init__.py,sha256=FJRcJ-B1Viyn-38L8XpOpZ8KOnf1I7PCDOAmKXLQhqc,71
14
+ digitalkin/core/common/__init__.py,sha256=Gh2eJAJRnrUE93jSEfG7r0nb01Xh1kSkNL6nEpfzK_s,218
15
+ digitalkin/core/common/factories.py,sha256=mV6SmXXrZxzIQ7DLdDtPdjapSDZt5Ua-nBIDsozs_Vk,5047
14
16
  digitalkin/core/job_manager/__init__.py,sha256=gGtgQpE6vbBHxAj1SYMbcpj45Q6x8IcsqnyQPfyZZ-8,25
15
- digitalkin/core/job_manager/base_job_manager.py,sha256=tkm-nT_SuctG4cSzMbvo25zwS8WSaMf-dF8MWnXnO6I,6441
16
- digitalkin/core/job_manager/single_job_manager.py,sha256=7wswR1hJ-yM6nLPi-7ibyvdMlG3I4pKKdW8TVsGFGWw,11078
17
- digitalkin/core/job_manager/taskiq_broker.py,sha256=qnN45i688z81WnEbpeoaiT9R60udnLmvCCW-XLm10y8,7461
18
- digitalkin/core/job_manager/taskiq_job_manager.py,sha256=UsqBsSYm88ibgRabSVPzK-9o2iXtGPsRlUO58M_PqVA,10147
17
+ digitalkin/core/job_manager/base_job_manager.py,sha256=yVaakJNIEPWc6ND1bWrUgBA-8r1yEEQZ_iNP1RnK0jY,10076
18
+ digitalkin/core/job_manager/single_job_manager.py,sha256=7MkttI7pP0aZUHgz8apQf3kXHNI3Mbh8F5LfKwLhRpo,13789
19
+ digitalkin/core/job_manager/taskiq_broker.py,sha256=ti-wb9yNsspQEDOCbL0OhUwsvcA447lLKywjvKHgVQA,11406
20
+ digitalkin/core/job_manager/taskiq_job_manager.py,sha256=IQ2g34mA_AsbIHNiSpzxxT6KzoOEUVb_67659LgBT_4,21251
19
21
  digitalkin/core/task_manager/__init__.py,sha256=k9i-qIoee_1yXogyQolaVFDUQBIZU3ENbYKtjrCNmTQ,31
20
- digitalkin/core/task_manager/surrealdb_repository.py,sha256=bmKaUoLTGfF-26zG_lX8mD-0dL3eTNr-BerUkSH7T2k,7739
21
- digitalkin/core/task_manager/task_manager.py,sha256=7wzilf2C4PvGXJVzc2sE_ZL9YrVoQ44E8kRcioP1OOw,16378
22
- digitalkin/core/task_manager/task_session.py,sha256=tjXm0gZOYxrnyzr07x6DtB6vZRl2U7BDBNEitSJwxLs,10525
22
+ digitalkin/core/task_manager/base_task_manager.py,sha256=ahkflSul07hMAWRX22CoJf9FxpQhWzi_oKZz3YAN6lc,19416
23
+ digitalkin/core/task_manager/local_task_manager.py,sha256=Z1gv4dCGD32LBSfMZJ4dGyYDe80lZRAyowTgGC6E4Vk,3534
24
+ digitalkin/core/task_manager/remote_task_manager.py,sha256=zgccmnwwtB0nyeIZlL5Ji8SY1J89z_vjA4JD9ur7HzY,3082
25
+ digitalkin/core/task_manager/surrealdb_repository.py,sha256=eNOVrYhTiIM0jd8j46fsKDr_THbGdK3xrog2jeqSQyA,9671
26
+ digitalkin/core/task_manager/task_executor.py,sha256=8xh5_1zuRAaGZIH_gWyNsA4T7YYaF0sl51dLS8a6aAk,10981
27
+ digitalkin/core/task_manager/task_session.py,sha256=ZU2GqtWAZidG7M7K_6GgEemBKRZ_RP2pW-3ODQSqP84,13665
23
28
  digitalkin/grpc_servers/__init__.py,sha256=ZIRMJ1Lcas8yQ106GCup6hn2UBOsx1sNk8ap0lpEDnY,72
24
29
  digitalkin/grpc_servers/_base_server.py,sha256=ZVeCDwI7w7fFbPTXPkeJb_SOuLfd2T7za3T4oCu2UWY,18680
25
- digitalkin/grpc_servers/module_server.py,sha256=kXvPOfJ9LT9oRd5oPj-ZpYB9EYY_4RDlRpcyGzWkilc,10213
26
- digitalkin/grpc_servers/module_servicer.py,sha256=Rr1Cq2zMaiu9oRAdjgmIlfLa_QDFzWPDamzzhE-mgzU,19365
27
- digitalkin/grpc_servers/registry_server.py,sha256=7jNzGiacr6XOm4EdHN7tHhaA_J0q70y38Xxbnlt8WxQ,2224
28
- digitalkin/grpc_servers/registry_servicer.py,sha256=dqsKGHZ0LnaIvGt4ipaAuigd37sbJBndT4MAT029GsY,16471
30
+ digitalkin/grpc_servers/module_server.py,sha256=fJncoCQ-nHK4rs1PFM99Ds0U1Axjxj1X4ILeud96AvM,10235
31
+ digitalkin/grpc_servers/module_servicer.py,sha256=V8rlOUKGF4wq27dBtCpqvYUd0WVgXRDBB7jaGtofTck,19724
32
+ digitalkin/grpc_servers/registry_server.py,sha256=v4pFpkcnWHL3Sm4CHw8wTKbSAvppEYgg_ikgdirmazc,2235
33
+ digitalkin/grpc_servers/registry_servicer.py,sha256=5AaGacM875fHCiOmMRuqx4Q3ZsR5yvdfjuRsV4xhRcA,16485
29
34
  digitalkin/grpc_servers/utils/__init__.py,sha256=ZnAIb_F8z4NhtPypqkdmzgRSzolKnJTk3oZx5GfWH5Y,38
30
35
  digitalkin/grpc_servers/utils/exceptions.py,sha256=LtaDtlqXCeT6iqApogs4pbtezotOVeg4fhnFzGBvFsY,692
31
36
  digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=a4xeulweovugI-IUVBrSZ-CswZHrBdeh9r-yzP8dl1w,2753
37
+ digitalkin/grpc_servers/utils/grpc_error_handler.py,sha256=0wPEU4713_ZlgIilaeXJV2bi90tHwYO1myDrSLeenKk,1848
32
38
  digitalkin/mixins/__init__.py,sha256=d6ljaoyJZJT9XxOrXZG5FVNvbLURb3_CZrkp4GPZWYM,590
33
39
  digitalkin/mixins/base_mixin.py,sha256=uLkg6MbDtVc9DysjdfNIGKahxQLnnjuL3DYpuyNLbk8,486
34
40
  digitalkin/mixins/callback_mixin.py,sha256=90nHm9-pbKT14GAy3CB3fsBtpYu5IH0woOQdNLM2e_Y,836
@@ -41,37 +47,37 @@ digitalkin/mixins/storage_mixin.py,sha256=ptZ4a2bydIa48q0V9e395vWHTu7yw4A6rI4jwK
41
47
  digitalkin/models/__init__.py,sha256=hDHtUfswaNh8wo4NZaBItg9JqC0uNSRqXArNWSrGynY,163
42
48
  digitalkin/models/core/__init__.py,sha256=jOMDmPX0uSfGA9zUi0u_kOvYJ46VdIssoIhVYvNSeew,19
43
49
  digitalkin/models/core/job_manager_models.py,sha256=RCrW20HCTQ7l2D1JtNgEKefZpMzoN-uAXK8bPorIqqA,1120
44
- digitalkin/models/core/task_monitor.py,sha256=JBMzqaKLrsxb0QZYM1BlvCxxkbqD_YKgsWob7bsmBeE,1626
50
+ digitalkin/models/core/task_monitor.py,sha256=XNYCxhN9QqJZhuO2LoiWEHZwhA35dsupyfYvek_pgE8,2295
45
51
  digitalkin/models/grpc_servers/__init__.py,sha256=0tA71nPSXgRrh9DoLvx-TSwZXdYIRUEItoadpTL1cTo,42
46
- digitalkin/models/grpc_servers/models.py,sha256=ZQ1Gk4zmLRX_ueuwFOwXgtyG9OEPSzFa_91I_CXZmZ0,8957
52
+ digitalkin/models/grpc_servers/models.py,sha256=unV1Wo0u3Efm7ddgYyYZZYUC_W6F0S5BQYH3xsOmXjw,8965
47
53
  digitalkin/models/grpc_servers/types.py,sha256=rQ78s4nAet2jy-NIDj_PUWriT0kuGHr_w6ELjmjgBao,539
48
54
  digitalkin/models/module/__init__.py,sha256=nFPHp0JcAZq9ISkcSu1y2zeNyXH3V4j10oMjHzMBYBU,599
49
55
  digitalkin/models/module/module.py,sha256=k0W8vfJJFth8XdDzkHm32SyTuSf3h2qF0hSrxAfGF1s,956
50
- digitalkin/models/module/module_context.py,sha256=0sKIvLYt0KHR4oF0MUQ4RQZDBrPjmOSaIHNMcl7vUmI,4649
51
- digitalkin/models/module/module_types.py,sha256=kkOst1OWeQVzLdf0P8JBlZqf2LLWj14-bQHyYvwUN8Y,3562
56
+ digitalkin/models/module/module_context.py,sha256=Ykul3foD_-dpn-b54vkTeGOYvktagMp2fFEkCI_1-5A,4905
57
+ digitalkin/models/module/module_types.py,sha256=Z46NPBCf8yDot4ZT_iJfBMo8J-IhpYiJJlKJsXxe6vA,14445
52
58
  digitalkin/models/services/__init__.py,sha256=jhfVw6egq0OcHmos_fypH9XFehbHTBw09wluVFVFEyw,226
53
59
  digitalkin/models/services/cost.py,sha256=9PXvd5RrIk9vCrRjcUGQ9ZyAokEbwLg4s0RfnE-aLP4,1616
54
60
  digitalkin/models/services/storage.py,sha256=wp7F-AvTsU46ujGPcguqM5kUKRZx4399D4EGAAJt2zs,1143
55
61
  digitalkin/modules/__init__.py,sha256=VwVbKok81NGyPIBZgEj_SR-59G8tTlSb4eBJI9W6Vx4,281
56
- digitalkin/modules/_base_module.py,sha256=UDLPbsVqlRdvT1weJ_Skzgv7R16TOyfSWeddg5ZqxzI,16513
62
+ digitalkin/modules/_base_module.py,sha256=g9QhgZAkTOei7_eB76Yg6WX87noN2G8V016FF6guTEk,18359
57
63
  digitalkin/modules/archetype_module.py,sha256=lOe3yYufwfylZR_VGy1w-zqdqVaMI_JANfKkbH9eODE,471
58
64
  digitalkin/modules/tool_module.py,sha256=rLJfdYMWddiUgPLBDGG_UcHnRCHEeaqX6Fdp4DOUaCs,472
59
65
  digitalkin/modules/trigger_handler.py,sha256=qPNMi-8NHqscOxciHeaXtpwjXApT3YzjMF23zQAjaZY,1770
60
66
  digitalkin/services/__init__.py,sha256=LqGk_5DJy8Bzz62ajIq9jCeYNKQUIgtSCpafZk15FLc,910
61
67
  digitalkin/services/base_strategy.py,sha256=yA9KUJGRKuuaxA6l3GcMv8zKfWoIsW03UxJT80Yea2I,766
62
- digitalkin/services/services_config.py,sha256=JnyzZcG7OYBelwgn-wdVgY2n3yFTEkwLPHRZB8Tjw10,7468
63
- digitalkin/services/services_models.py,sha256=5zXkWcfKnXGwQi9sN4OAL3XrgqOcmsTl8ai5Mi4RPsw,1668
68
+ digitalkin/services/services_config.py,sha256=r9h6iYdsIifyBxaEEuZ4cKRPo3u-703Ea9hOjiK3GLU,8063
69
+ digitalkin/services/services_models.py,sha256=0HmveQ1H-dvGRl1ljFSpWNlLWIiDhbhyqKUxq5UjbLo,1759
64
70
  digitalkin/services/agent/__init__.py,sha256=vJc8JN0pdtA8ecypLBeHrwAUIW6H2C8NyW-dk24rTpk,244
65
71
  digitalkin/services/agent/agent_strategy.py,sha256=42Q9RciHX6tg3CgDQkbrlIx4h_TX0WIuSpLmCjitVmA,492
66
72
  digitalkin/services/agent/default_agent.py,sha256=4N_E_eQxJGOx1KVUUg5jNOje-3ncMxF3ePB-uDuGrJc,345
67
73
  digitalkin/services/cost/__init__.py,sha256=sD_a5LrnLluASOC5m5vgIqjaco-MzZJd6XhillIBHr0,400
68
74
  digitalkin/services/cost/cost_strategy.py,sha256=MpPX33P_S5b2by6F4zT-rcyeRuh2V4NYPZe05VpDOGQ,2649
69
75
  digitalkin/services/cost/default_cost.py,sha256=XE7kNFde8NmbulU9m1lc3mi-vHFkbaJf0XHUc0D4UHE,3945
70
- digitalkin/services/cost/grpc_cost.py,sha256=wX6lrIAl92ErVe_4xjBg2z7y9Aoziv8aLVA_J3PKEHE,6296
76
+ digitalkin/services/cost/grpc_cost.py,sha256=B4HlrpsOpeq7jLSDyympOXvl6uXAzq_Ifk4t1EGjCpI,5289
71
77
  digitalkin/services/filesystem/__init__.py,sha256=BhwMl_BUvM0d65fmglkp0SVwn3RfYiUOKJgIMnOCaGM,381
72
78
  digitalkin/services/filesystem/default_filesystem.py,sha256=WQbU-Bsi9r-28VqhKbrplce3otzjSKS-5iqKEpGWdQU,15117
73
79
  digitalkin/services/filesystem/filesystem_strategy.py,sha256=zibVLvX_IBQ-kgh-KYzHdszDeiHFPEAZszu_k99x1GQ,9487
74
- digitalkin/services/filesystem/grpc_filesystem.py,sha256=-gSA8Bmuea73DbBEG8x5b6-E0bQuT5WrK6xdSbOlH5M,12988
80
+ digitalkin/services/filesystem/grpc_filesystem.py,sha256=TSj70so3YxeuTXSvSFJrA6LHwM07HNZ9kDdqCBAbC70,12154
75
81
  digitalkin/services/identity/__init__.py,sha256=InkeyLgFYYwItx8mePA8HpfacOMWZwwuc0G4pWtKq9s,270
76
82
  digitalkin/services/identity/default_identity.py,sha256=Y2auZHrGSZTIN5D8HyjLvLcNbYFM1CNUE23x7p5VIGw,386
77
83
  digitalkin/services/identity/identity_strategy.py,sha256=skappBbds1_qa0Gr24FGrNX1N0_OYhYT1Lh7dUaAirE,429
@@ -79,29 +85,35 @@ digitalkin/services/registry/__init__.py,sha256=Zl4QAkCe9tOmmKGBWVuLQVFepdZiL0ec
79
85
  digitalkin/services/registry/default_registry.py,sha256=VnWkF6nHpFxUKuUbZLPqzXqdA6oXmyV_ySpeuOCf_ko,277
80
86
  digitalkin/services/registry/registry_strategy.py,sha256=uBXgZIv25jeXbeVO8vWvlNPxxNYu7_KiCw2PoE6AWr8,423
81
87
  digitalkin/services/setup/__init__.py,sha256=t6xcvEWqTbcRZstBFK9cESEqaZKvpW14VtYygxIqfYQ,65
82
- digitalkin/services/setup/default_setup.py,sha256=9VM3KwsuQcFQQ08RoOHWOE_-9BsRW0YGRtDWYTbQGdA,8246
83
- digitalkin/services/setup/grpc_setup.py,sha256=PSfZhzPxln6fxAvFo1dL8CJBBSERPezdKp9zmkU425g,12481
88
+ digitalkin/services/setup/default_setup.py,sha256=fnLSCMFQt5bYxbiOLM6wgP0ElIf1j9hf8whhogvl6Sg,8239
89
+ digitalkin/services/setup/grpc_setup.py,sha256=52nRFWLxnDSAWRacve04nRguiIQZAWMM-gcoiwxJ8Mo,13942
84
90
  digitalkin/services/setup/setup_strategy.py,sha256=ZnJ_HwWCkHCPrqKekSD5L9y3p8wMwfjQ8sj2hLZq6go,4004
85
91
  digitalkin/services/snapshot/__init__.py,sha256=Uzlnzo0CYlSpVsdiI37hW7xQk8hu3YA1fOI6O6MSzB0,270
86
92
  digitalkin/services/snapshot/default_snapshot.py,sha256=Mb8QwWRsHh9I_tN0ln_ZiFa1QCZxOVWmuVLemQOTWpc,1058
87
93
  digitalkin/services/snapshot/snapshot_strategy.py,sha256=B1TU3V_k9A-OdqBkdyc41-ihnrW5Btcwd1KyQdHT46A,898
88
94
  digitalkin/services/storage/__init__.py,sha256=T-ocYLLphudkQgzvG47jBOm5GQsRFRIGA88y7Ur4akg,341
89
95
  digitalkin/services/storage/default_storage.py,sha256=D8e-UYUkb2GvDEHMWcN3EkcIKXWA8DrsaQsXVjoXAYQ,7975
90
- digitalkin/services/storage/grpc_storage.py,sha256=ONilhj0-ySLqPUqWI-UfxRsSgu89zbyohcOXt5EcSdU,7205
96
+ digitalkin/services/storage/grpc_storage.py,sha256=fFg83gvwJZW1a7f2AwSrxJFx949-KbNwpakPaCuGEvo,7217
91
97
  digitalkin/services/storage/storage_strategy.py,sha256=sERF5tIJnzpb1iNqTXic9xRkGaXMifo6kb709ubB-Yo,8848
92
- digitalkin/utils/__init__.py,sha256=sJnY-ZUgsjMfojAjONC1VN14mhgIDnzyOlGkw21rRnM,28
98
+ digitalkin/services/user_profile/__init__.py,sha256=RKEZCsgCHS7fmswhWgUoQd6vZ_1pYnRqERoF8fmu7jw,434
99
+ digitalkin/services/user_profile/default_user_profile.py,sha256=46DH_VBCHKXJVyagVcc8kH5sLwRK54Fe_0ahqYJ1maA,1847
100
+ digitalkin/services/user_profile/grpc_user_profile.py,sha256=VBjXTySGBJO7cQ_hMsdYSUUyk3KFykeQqed82LlTihk,2811
101
+ digitalkin/services/user_profile/user_profile_strategy.py,sha256=luzpPvm2f4xXajWAbRGSk5YCIPBUrn5EOrXSz8NL1So,1148
102
+ digitalkin/utils/__init__.py,sha256=gDoEk5CP8tiBmIq-38aPhIMlnDUiqRrduuVXhpSPQnc,541
93
103
  digitalkin/utils/arg_parser.py,sha256=wzscRlE1Qp1gGl-lAJlkkwnbU1O2oezj6BwK_BZFBIk,3158
94
104
  digitalkin/utils/development_mode_action.py,sha256=2hznh0ajW_4ZTysfoc0Y49161f_PQPATRgNk8NAn1_o,1623
105
+ digitalkin/utils/dynamic_schema.py,sha256=5-B3dBGlCYYv6uRJkgudtc0ZpBOTYxl0yKedDGsteZQ,15184
95
106
  digitalkin/utils/llm_ready_schema.py,sha256=JjMug_lrQllqFoanaC091VgOqwAd-_YzcpqFlS7p778,2375
96
107
  digitalkin/utils/package_discover.py,sha256=sa6Zp5Kape1Zr4iYiNrnZxiHDnqM06ODk6yfWHom53w,13465
97
- digitalkin-0.3.0rc1.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
108
+ digitalkin-0.3.1.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
98
109
  modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
99
110
  modules/cpu_intensive_module.py,sha256=ejB9XPnFfA0uCuFUQbM3fy5UYfqqAlF36rv_P5Ri8ho,8363
111
+ modules/dynamic_setup_module.py,sha256=GPJwfaPZUkcOlMX9d_sYUDzT8aPrfjrCCQ4OyPtulD8,12507
100
112
  modules/minimal_llm_module.py,sha256=Ijld__ZnhzfLwpXD1XVkLZ7jyKZKyOFZczOpiPttJZc,11216
101
113
  modules/text_transform_module.py,sha256=bwPSnEUthZQyfLwcTLo52iAxItAoknkLh8Y3m5aywaY,7251
102
114
  services/filesystem_module.py,sha256=71Mcja8jCQqiqFHPdsIXplFIHTvgkxRhp0TRXuCfgkk,7430
103
115
  services/storage_module.py,sha256=ybTMqmvGaTrR8PqJ4FU0cwxaDjT36TskVrGoetTGmno,6955
104
- digitalkin-0.3.0rc1.dist-info/METADATA,sha256=dpzbrevBvxDMjGm2fHdKxEI5V3y2WVzV-mpIwpqGA8g,30651
105
- digitalkin-0.3.0rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
106
- digitalkin-0.3.0rc1.dist-info/top_level.txt,sha256=gcjqlyrZuLjIyxrOIavCQM_olpr6ND5kPKkZd2j0xGo,40
107
- digitalkin-0.3.0rc1.dist-info/RECORD,,
116
+ digitalkin-0.3.1.dist-info/METADATA,sha256=TLih9e_7ssTTi6R8maDOVg7J4TZkdILV_qR9jYbGjqk,29709
117
+ digitalkin-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
118
+ digitalkin-0.3.1.dist-info/top_level.txt,sha256=gcjqlyrZuLjIyxrOIavCQM_olpr6ND5kPKkZd2j0xGo,40
119
+ digitalkin-0.3.1.dist-info/RECORD,,
@@ -0,0 +1,362 @@
1
+ """Example module demonstrating dynamic schema fields in SetupModel.
2
+
3
+ This example shows how to use the Dynamic metadata class with async fetchers
4
+ to populate field schemas (like enums) at runtime. This is useful when the
5
+ available options come from external sources like databases or APIs.
6
+
7
+ Usage:
8
+ # Start the module server
9
+ python examples/modules/dynamic_setup_module.py
10
+
11
+ # Or import and use in your own code
12
+ from examples.modules.dynamic_setup_module import DynamicSetupModule
13
+ """
14
+
15
+ import asyncio
16
+ import logging
17
+ from typing import Annotated, Any, ClassVar
18
+
19
+ from pydantic import BaseModel, Field
20
+
21
+ from digitalkin.models.module.module_context import ModuleContext
22
+ from digitalkin.models.module.module_types import DataModel, DataTrigger, SetupModel
23
+ from digitalkin.modules._base_module import BaseModule
24
+ from digitalkin.services.services_models import ServicesStrategy
25
+ from digitalkin.utils import Dynamic
26
+
27
+ # Configure logging
28
+ logging.basicConfig(
29
+ level=logging.DEBUG,
30
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
31
+ )
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ # =============================================================================
36
+ # Simulated External Services (replace with real implementations)
37
+ # =============================================================================
38
+
39
+
40
+ class MockModelRegistry:
41
+ """Simulates an external model registry service.
42
+
43
+ In a real application, this would be a connection to a database,
44
+ API service, or configuration management system.
45
+ """
46
+
47
+ _models: ClassVar[list[str]] = ["gpt-4", "gpt-4-turbo", "gpt-3.5-turbo"]
48
+ _languages: ClassVar[list[str]] = ["en", "fr", "de", "es", "it", "pt"]
49
+
50
+ @classmethod
51
+ async def fetch_available_models(cls) -> list[str]:
52
+ """Fetch available models from the registry.
53
+
54
+ Simulates an async API call with a small delay.
55
+ """
56
+ await asyncio.sleep(0.1) # Simulate network latency
57
+ logger.info("Fetched %d models from registry", len(cls._models))
58
+ return cls._models.copy()
59
+
60
+ @classmethod
61
+ async def fetch_supported_languages(cls) -> list[str]:
62
+ """Fetch supported languages from the registry."""
63
+ await asyncio.sleep(0.05) # Simulate network latency
64
+ logger.info("Fetched %d languages from registry", len(cls._languages))
65
+ return cls._languages.copy()
66
+
67
+ @classmethod
68
+ def get_default_model(cls) -> str:
69
+ """Get the default model (sync fetcher example)."""
70
+ return cls._models[0] if cls._models else "gpt-4"
71
+
72
+
73
+ # =============================================================================
74
+ # Dynamic Fetcher Functions
75
+ # =============================================================================
76
+
77
+
78
+ async def fetch_models() -> list[str]:
79
+ """Async fetcher for available model names.
80
+
81
+ This function is called when SetupModel.get_clean_model(force=True)
82
+ is invoked, typically during module initialization or schema refresh.
83
+ """
84
+ return await MockModelRegistry.fetch_available_models()
85
+
86
+
87
+ async def fetch_languages() -> list[str]:
88
+ """Async fetcher for supported languages."""
89
+ return await MockModelRegistry.fetch_supported_languages()
90
+
91
+
92
+ def get_temperature_range() -> dict[str, float]:
93
+ """Sync fetcher example returning min/max for temperature.
94
+
95
+ Demonstrates that fetchers can return any JSON-serializable value,
96
+ not just lists for enums.
97
+ """
98
+ return {"minimum": 0.0, "maximum": 2.0}
99
+
100
+
101
+ # =============================================================================
102
+ # Setup Model with Dynamic Fields
103
+ # =============================================================================
104
+
105
+
106
+ class DynamicAgentSetup(SetupModel):
107
+ """Setup model demonstrating dynamic schema fields.
108
+
109
+ Fields marked with Dynamic(...) will have their schema values
110
+ refreshed at runtime when get_clean_model(force=True) is called.
111
+
112
+ Attributes:
113
+ model_name: The LLM model to use. Enum values fetched from registry.
114
+ language: Output language. Enum values fetched dynamically.
115
+ temperature: Sampling temperature. Static field for comparison.
116
+ max_tokens: Maximum tokens to generate.
117
+ system_prompt: The system prompt for the model.
118
+ """
119
+
120
+ # Dynamic field: enum values fetched asynchronously from model registry
121
+ model_name: Annotated[str, Dynamic(enum=fetch_models)] = Field(
122
+ default="gpt-4",
123
+ title="Model Name",
124
+ description="The LLM model to use for generation.",
125
+ json_schema_extra={
126
+ "config": True, # Shown in initial configuration
127
+ "ui:widget": "select",
128
+ },
129
+ )
130
+
131
+ # Dynamic field: language options fetched asynchronously
132
+ language: Annotated[str, Dynamic(enum=fetch_languages)] = Field(
133
+ default="en",
134
+ title="Output Language",
135
+ description="The language for generated responses.",
136
+ json_schema_extra={
137
+ "config": True,
138
+ "ui:widget": "select",
139
+ },
140
+ )
141
+
142
+ # Static field: no dynamic fetcher, values defined at class time
143
+ temperature: float = Field(
144
+ default=0.7,
145
+ ge=0.0,
146
+ le=2.0,
147
+ title="Temperature",
148
+ description="Controls randomness. Higher values = more creative.",
149
+ json_schema_extra={"config": True},
150
+ )
151
+
152
+ # Static field with hidden flag (runtime-only, not in initial config)
153
+ max_tokens: int = Field(
154
+ default=1024,
155
+ ge=1,
156
+ le=4096,
157
+ title="Max Tokens",
158
+ description="Maximum tokens in the response.",
159
+ json_schema_extra={"hidden": True},
160
+ )
161
+
162
+ # Static field without any special flags
163
+ system_prompt: str = Field(
164
+ default="You are a helpful assistant.",
165
+ title="System Prompt",
166
+ description="The system prompt defining assistant behavior.",
167
+ )
168
+
169
+
170
+ # =============================================================================
171
+ # Input/Output Models (Using DataModel/DataTrigger pattern)
172
+ # =============================================================================
173
+
174
+
175
+ class MessageInputTrigger(DataTrigger):
176
+ """Message input trigger following DigitalKin DataTrigger pattern.
177
+
178
+ The protocol field determines which trigger handler processes this input.
179
+ """
180
+
181
+ protocol: str = "message"
182
+ content: str = Field(default="", description="The user message content.")
183
+
184
+
185
+ class DynamicModuleInput(DataModel[MessageInputTrigger]):
186
+ """Input model following DigitalKin DataModel pattern.
187
+
188
+ Wraps the trigger in a root field with optional annotations.
189
+ """
190
+
191
+ root: MessageInputTrigger = Field(default_factory=MessageInputTrigger)
192
+
193
+
194
+ class MessageOutputTrigger(DataTrigger):
195
+ """Message output trigger following DigitalKin DataTrigger pattern."""
196
+
197
+ protocol: str = "message"
198
+ content: str = Field(default="", description="The generated response.")
199
+ model_used: str = Field(default="", description="The model that generated this response.")
200
+ language: str = Field(default="", description="The output language.")
201
+
202
+
203
+ class DynamicModuleOutput(DataModel[MessageOutputTrigger]):
204
+ """Output model following DigitalKin DataModel pattern."""
205
+
206
+ root: MessageOutputTrigger = Field(default_factory=MessageOutputTrigger)
207
+
208
+
209
+ class DynamicModuleSecret(BaseModel):
210
+ """Secret model (empty for this example)."""
211
+
212
+ pass
213
+
214
+
215
+ # =============================================================================
216
+ # Module Implementation
217
+ # =============================================================================
218
+
219
+
220
+ class DynamicSetupModule(
221
+ BaseModule[
222
+ DynamicModuleInput,
223
+ DynamicModuleOutput,
224
+ DynamicAgentSetup,
225
+ DynamicModuleSecret,
226
+ ]
227
+ ):
228
+ """Example module demonstrating dynamic schema in SetupModel.
229
+
230
+ This module shows how to:
231
+ 1. Define setup fields with Dynamic() metadata for runtime enum fetching
232
+ 2. Mix static and dynamic fields in the same SetupModel
233
+ 3. Use async fetchers that simulate external service calls
234
+ 4. Follow DigitalKin's DataModel/DataTrigger pattern for I/O
235
+
236
+ The key integration point is in the gRPC servicer, which calls
237
+ SetupModel.get_clean_model(force=True) to refresh dynamic values
238
+ before returning schema information to clients.
239
+ """
240
+
241
+ name = "DynamicSetupModule"
242
+ description = "Demonstrates dynamic schema fields in module setup"
243
+
244
+ # Schema format definitions
245
+ input_format = DynamicModuleInput
246
+ output_format = DynamicModuleOutput
247
+ setup_format = DynamicAgentSetup
248
+ secret_format = DynamicModuleSecret
249
+
250
+ # Module metadata
251
+ metadata: ClassVar[dict[str, Any]] = {
252
+ "name": "DynamicSetupModule",
253
+ "description": "Example module with dynamic setup schema",
254
+ "version": "1.0.0",
255
+ "tags": ["example", "dynamic-schema"],
256
+ }
257
+
258
+ # Services configuration (empty for this example)
259
+ services_config_strategies: ClassVar[dict[str, ServicesStrategy | None]] = {}
260
+ services_config_params: ClassVar[dict[str, dict[str, Any | None] | None]] = {}
261
+
262
+ async def initialize(self, context: ModuleContext, setup_data: DynamicAgentSetup) -> None:
263
+ """Initialize the module with setup data.
264
+
265
+ Args:
266
+ context: The module context with services and session info.
267
+ setup_data: The validated setup configuration.
268
+ """
269
+ logger.info(
270
+ "Initializing DynamicSetupModule with model=%s, language=%s",
271
+ setup_data.model_name,
272
+ setup_data.language,
273
+ )
274
+ self.setup = setup_data
275
+
276
+ async def cleanup(self) -> None:
277
+ """Clean up resources."""
278
+ logger.info("Cleaning up DynamicSetupModule")
279
+
280
+
281
+ # =============================================================================
282
+ # Demonstration Script
283
+ # =============================================================================
284
+
285
+
286
+ async def demonstrate_dynamic_schema() -> None:
287
+ """Demonstrate the dynamic schema functionality."""
288
+ print("=" * 60)
289
+ print("Dynamic Schema Demonstration")
290
+ print("=" * 60)
291
+
292
+ # 1. Show schema WITHOUT force (dynamic fields not resolved)
293
+ print("\n1. Schema without force=True (fetchers NOT called):")
294
+ print("-" * 40)
295
+
296
+ model_no_force = await DynamicAgentSetup.get_clean_model(
297
+ config_fields=True,
298
+ hidden_fields=False,
299
+ force=False,
300
+ )
301
+ schema_no_force = model_no_force.model_json_schema()
302
+
303
+ # Check if enum is present
304
+ model_name_schema = schema_no_force.get("properties", {}).get("model_name", {})
305
+ print(f"model_name has enum: {'enum' in model_name_schema}")
306
+ if "enum" in model_name_schema:
307
+ print(f" enum values: {model_name_schema['enum']}")
308
+
309
+ # 2. Show schema WITH force (dynamic fields resolved)
310
+ print("\n2. Schema with force=True (fetchers called):")
311
+ print("-" * 40)
312
+
313
+ model_with_force = await DynamicAgentSetup.get_clean_model(
314
+ config_fields=True,
315
+ hidden_fields=False,
316
+ force=True,
317
+ )
318
+ schema_with_force = model_with_force.model_json_schema()
319
+
320
+ # Check enum values after force
321
+ model_name_schema = schema_with_force.get("properties", {}).get("model_name", {})
322
+ print(f"model_name has enum: {'enum' in model_name_schema}")
323
+ if "enum" in model_name_schema:
324
+ print(f" enum values: {model_name_schema['enum']}")
325
+
326
+ language_schema = schema_with_force.get("properties", {}).get("language", {})
327
+ print(f"language has enum: {'enum' in language_schema}")
328
+ if "enum" in language_schema:
329
+ print(f" enum values: {language_schema['enum']}")
330
+
331
+ # 3. Show that static json_schema_extra is preserved
332
+ print("\n3. Static json_schema_extra preserved:")
333
+ print("-" * 40)
334
+ print(f"model_name ui:widget: {model_name_schema.get('ui:widget', 'NOT FOUND')}")
335
+
336
+ # 4. Show field filtering
337
+ print("\n4. Field filtering demonstration:")
338
+ print("-" * 40)
339
+
340
+ # Config fields only (hidden excluded)
341
+ config_model = await DynamicAgentSetup.get_clean_model(
342
+ config_fields=True,
343
+ hidden_fields=False,
344
+ force=False,
345
+ )
346
+ print(f"Config fields (hidden=False): {list(config_model.model_fields.keys())}")
347
+
348
+ # All fields including hidden
349
+ all_model = await DynamicAgentSetup.get_clean_model(
350
+ config_fields=True,
351
+ hidden_fields=True,
352
+ force=False,
353
+ )
354
+ print(f"All fields (hidden=True): {list(all_model.model_fields.keys())}")
355
+
356
+ print("\n" + "=" * 60)
357
+ print("Demonstration complete!")
358
+ print("=" * 60)
359
+
360
+
361
+ if __name__ == "__main__":
362
+ asyncio.run(demonstrate_dynamic_schema())