orchestrator-core 4.6.1__py3-none-any.whl → 4.6.3__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 (55) hide show
  1. orchestrator/__init__.py +1 -1
  2. orchestrator/api/api_v1/endpoints/processes.py +4 -1
  3. orchestrator/api/api_v1/endpoints/search.py +44 -34
  4. orchestrator/{search/retrieval/utils.py → cli/search/display.py} +4 -29
  5. orchestrator/cli/search/search_explore.py +22 -24
  6. orchestrator/cli/search/speedtest.py +11 -9
  7. orchestrator/db/models.py +6 -6
  8. orchestrator/graphql/resolvers/helpers.py +15 -0
  9. orchestrator/graphql/resolvers/process.py +5 -3
  10. orchestrator/graphql/resolvers/product.py +3 -2
  11. orchestrator/graphql/resolvers/product_block.py +3 -2
  12. orchestrator/graphql/resolvers/resource_type.py +3 -2
  13. orchestrator/graphql/resolvers/scheduled_tasks.py +3 -1
  14. orchestrator/graphql/resolvers/settings.py +2 -0
  15. orchestrator/graphql/resolvers/subscription.py +5 -3
  16. orchestrator/graphql/resolvers/version.py +2 -0
  17. orchestrator/graphql/resolvers/workflow.py +3 -2
  18. orchestrator/graphql/schemas/process.py +3 -3
  19. orchestrator/log_config.py +2 -0
  20. orchestrator/schemas/search.py +1 -1
  21. orchestrator/schemas/search_requests.py +59 -0
  22. orchestrator/search/agent/handlers.py +129 -0
  23. orchestrator/search/agent/prompts.py +54 -33
  24. orchestrator/search/agent/state.py +9 -24
  25. orchestrator/search/agent/tools.py +223 -144
  26. orchestrator/search/agent/validation.py +80 -0
  27. orchestrator/search/{schemas → aggregations}/__init__.py +20 -0
  28. orchestrator/search/aggregations/base.py +201 -0
  29. orchestrator/search/core/types.py +3 -2
  30. orchestrator/search/filters/__init__.py +4 -0
  31. orchestrator/search/filters/definitions.py +22 -1
  32. orchestrator/search/filters/numeric_filter.py +3 -3
  33. orchestrator/search/llm_migration.py +2 -1
  34. orchestrator/search/query/__init__.py +90 -0
  35. orchestrator/search/query/builder.py +285 -0
  36. orchestrator/search/query/engine.py +162 -0
  37. orchestrator/search/{retrieval → query}/exceptions.py +38 -7
  38. orchestrator/search/query/mixins.py +95 -0
  39. orchestrator/search/query/queries.py +129 -0
  40. orchestrator/search/query/results.py +252 -0
  41. orchestrator/search/{retrieval/query_state.py → query/state.py} +31 -11
  42. orchestrator/search/{retrieval → query}/validation.py +58 -1
  43. orchestrator/search/retrieval/__init__.py +0 -5
  44. orchestrator/search/retrieval/pagination.py +7 -8
  45. orchestrator/search/retrieval/retrievers/base.py +9 -9
  46. orchestrator/workflows/translations/en-GB.json +1 -0
  47. {orchestrator_core-4.6.1.dist-info → orchestrator_core-4.6.3.dist-info}/METADATA +16 -15
  48. {orchestrator_core-4.6.1.dist-info → orchestrator_core-4.6.3.dist-info}/RECORD +51 -45
  49. orchestrator/search/retrieval/builder.py +0 -127
  50. orchestrator/search/retrieval/engine.py +0 -197
  51. orchestrator/search/schemas/parameters.py +0 -133
  52. orchestrator/search/schemas/results.py +0 -80
  53. /orchestrator/search/{export.py → query/export.py} +0 -0
  54. {orchestrator_core-4.6.1.dist-info → orchestrator_core-4.6.3.dist-info}/WHEEL +0 -0
  55. {orchestrator_core-4.6.1.dist-info → orchestrator_core-4.6.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,9 @@
1
- orchestrator/__init__.py,sha256=nmpevZN48uSDOt0dNDWo92ZW--o53apq2S5b1q1mUn4,1454
1
+ orchestrator/__init__.py,sha256=kUPxKX8HanrEfxBTsedmPwi5wHf5sPtu6DhGUR3R_I0,1454
2
2
  orchestrator/agentic_app.py,sha256=ouiyyZiS4uS6Lox2DtbGGRnb2njJBMSHpSAGe-T5rX0,3028
3
3
  orchestrator/app.py,sha256=w8ubXaaogwjmwLM0TXqZaLkAhmaOTWzVlwiYbi5mHeE,13203
4
4
  orchestrator/exception_handlers.py,sha256=UsW3dw8q0QQlNLcV359bIotah8DYjMsj2Ts1LfX4ClY,1268
5
5
  orchestrator/llm_settings.py,sha256=giqxZmwO8sXyNF5Zc7-O9JYd7PLN065pKQYpJYOpXcE,2816
6
- orchestrator/log_config.py,sha256=1cPl_OXT4tEUyNxG8cwIWXrmadUm1E81vq0mdtrV-v4,1912
6
+ orchestrator/log_config.py,sha256=aCbIzKzDnVwF0zVoQ9TlvuHxn0uhJWRjNL72Hc5pcss,2031
7
7
  orchestrator/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  orchestrator/security.py,sha256=iXFxGxab54aav7oHEKLAVkTgrQMJGHy6IYLojEnD7gI,2422
9
9
  orchestrator/settings.py,sha256=mvs1VhBYth6Zp55HsNroML4DU1jiq5SkVM47_BLgcIo,4662
@@ -20,11 +20,11 @@ orchestrator/api/api_v1/api.py,sha256=1qQRsIxKXLW3kcmSV5u3_v1TZk5RcNWb4ZOyLguhTK
20
20
  orchestrator/api/api_v1/endpoints/__init__.py,sha256=GyHNfEFCGKQwRiN6rQmvSRH2iYX7npjMZn97n8XzmLU,571
21
21
  orchestrator/api/api_v1/endpoints/agent.py,sha256=9_s3nchTr9ua_1Sxs0kJl2mH_20o-DlUaaQPmY4vRMk,1732
22
22
  orchestrator/api/api_v1/endpoints/health.py,sha256=iaxs1XX1_250_gKNsspuULCV2GEMBjbtjsmfQTOvMAI,1284
23
- orchestrator/api/api_v1/endpoints/processes.py,sha256=OVbt6FgFnJ4aHaYGIg0cPoim8mxDpdzJ4TGAyfB_kPw,16269
23
+ orchestrator/api/api_v1/endpoints/processes.py,sha256=z_bantT415cCuAw0viVrsi7HquHKMSmdjnuLkk9OZKI,16324
24
24
  orchestrator/api/api_v1/endpoints/product_blocks.py,sha256=kZ6ywIOsS_S2qGq7RvZ4KzjvaS1LmwbGWR37AKRvWOw,2146
25
25
  orchestrator/api/api_v1/endpoints/products.py,sha256=BfFtwu9dZXEQbtKxYj9icc73GKGvAGMR5ytyf41nQlQ,3081
26
26
  orchestrator/api/api_v1/endpoints/resource_types.py,sha256=gGyuaDyOD0TAVoeFGaGmjDGnQ8eQQArOxKrrk4MaDzA,2145
27
- orchestrator/api/api_v1/endpoints/search.py,sha256=Zk3kDICF3ruaz0VUJH2q5GbbccLSdt9x4I5SN00M9EM,8133
27
+ orchestrator/api/api_v1/endpoints/search.py,sha256=R_OzfJfquoaTeGBwXTbomh16aYy0ael6_Xn3WkKfyjg,8575
28
28
  orchestrator/api/api_v1/endpoints/settings.py,sha256=5s-k169podZjgGHUbVDmSQwpY_3Cs_Bbf2PPtZIkBcw,6184
29
29
  orchestrator/api/api_v1/endpoints/subscription_customer_descriptions.py,sha256=1_6LtgQleoq3M6z_W-Qz__Bj3OFUweoPrUqHMwSH6AM,3288
30
30
  orchestrator/api/api_v1/endpoints/subscriptions.py,sha256=7KaodccUiMkcVnrFnK2azp_V_-hGudcIyhov5WwVGQY,9810
@@ -104,10 +104,11 @@ orchestrator/cli/helpers/__init__.py,sha256=GyHNfEFCGKQwRiN6rQmvSRH2iYX7npjMZn97
104
104
  orchestrator/cli/helpers/input_helpers.py,sha256=pv5GTMuIWLzBE_bKNhn1XD_gxoqB0s1ZN4cnKkIIu5I,1139
105
105
  orchestrator/cli/helpers/print_helpers.py,sha256=b3ePg6HfBLKPYBBVr5XOA__JnFEMI5HBjbjov3CP8Po,859
106
106
  orchestrator/cli/search/__init__.py,sha256=K15_iW9ogR7xtX7qHDal4H09tmwVGnOBZWyPBLWhuzc,1274
107
+ orchestrator/cli/search/display.py,sha256=PKy9sOTpq0WUdSfY2khLrIQ1OdAfsyl95ogF1Z6Dae0,3629
107
108
  orchestrator/cli/search/index_llm.py,sha256=RWPkFz5bxiznjpN1vMsSWeqcvYKB90DLL4pXQ92QJNI,2239
108
109
  orchestrator/cli/search/resize_embedding.py,sha256=iJdM7L6Kyq4CzRjXHWLwpGRiMnKK7xZ9133C0THebBE,4847
109
- orchestrator/cli/search/search_explore.py,sha256=SDn1DMN8a4roSPodIHl-KrNAvdHo5jTDUvMUFLVh1P4,8602
110
- orchestrator/cli/search/speedtest.py,sha256=4YGd2JsOHozuI3YMphO_GAJLJZ8KyL72ERhf_1RwABI,4812
110
+ orchestrator/cli/search/search_explore.py,sha256=LNAn6w13Q69fpv8CHcicHAbabrctrjGvwTjjJyC0AZY,8447
111
+ orchestrator/cli/search/speedtest.py,sha256=J_l-8WxgN3YnqmwnbRhDyVbeqtvk3d2SfIpRBOJuhvE,4840
111
112
  orchestrator/config/__init__.py,sha256=GyHNfEFCGKQwRiN6rQmvSRH2iYX7npjMZn97n8XzmLU,571
112
113
  orchestrator/config/assignee.py,sha256=9mFFe9hoi2NCkXFOKL2pU2aveBzcZhljSvqUnh55vrk,780
113
114
  orchestrator/db/__init__.py,sha256=I9QSWgqnenShixO_Kseuo0ZtM1epLAOIRpucxccrQDk,3625
@@ -115,7 +116,7 @@ orchestrator/db/database.py,sha256=MU_w_e95ho2dVb2JDnt_KFYholx___XDkiQXbc8wCkI,1
115
116
  orchestrator/db/helpers.py,sha256=L8kEdnSSNGnUpZhdeGx2arCodakWN8vSpKdfjoLuHdY,831
116
117
  orchestrator/db/listeners.py,sha256=UBPYcH0FE3a7aZQu_D0O_JMXpXIRYXC0gjSAvlv5GZo,1142
117
118
  orchestrator/db/loaders.py,sha256=ez6JzQ3IKVkC_oLAkVlIIiI8Do7hXbdcPKCvUSLxRog,7962
118
- orchestrator/db/models.py,sha256=vgYRMBiMzwDvePZBBkMrvflljfYHsAGNo6u6jUtC0QY,31328
119
+ orchestrator/db/models.py,sha256=AeBHLm0PLtoSAHoXzxjy9JsDQA5JhPvS7Ro55ynu_tk,31275
119
120
  orchestrator/db/filters/__init__.py,sha256=RUj6P0XxEBhYj0SN5wH5-Vf_Wt_ilZR_n9DSar5m9oM,371
120
121
  orchestrator/db/filters/filters.py,sha256=55RtpQwM2rhrk4A6CCSeSXoo-BT9GnQoNTryA8CtLEg,5020
121
122
  orchestrator/db/filters/process.py,sha256=xvGhyfo_MZ1xhLvFC6yULjcT4mJk0fKc1glJIYgsWLE,4018
@@ -178,23 +179,23 @@ orchestrator/graphql/mutations/customer_description.py,sha256=zm_X1yvWl4qC97_rYU
178
179
  orchestrator/graphql/mutations/start_process.py,sha256=8vLVvmBwL1ujbZJoI_8YE3VAgI-J2RTzgrTZJC8THZ4,1576
179
180
  orchestrator/graphql/resolvers/__init__.py,sha256=EEw9NO4LAryfrpkLlgsNQ9rytKd0usBDx95OURRV6sg,1031
180
181
  orchestrator/graphql/resolvers/customer.py,sha256=tq06MtMoaqFwqn3YQvSv0VmROW7QJZRJp1ykO4tUhck,934
181
- orchestrator/graphql/resolvers/helpers.py,sha256=8NeuiJD9CPus4BhRK9nDsSMhb2LhW1W7nrEpyj_J3M4,771
182
- orchestrator/graphql/resolvers/process.py,sha256=Hqs1F7-gw0yO_ioHjh2eLAyxrK2WSuL3VJ0y2ouNcLA,5010
183
- orchestrator/graphql/resolvers/product.py,sha256=uPBmYwMdau-zUqNjoDl-LDn927u3aCFW5JQ4A_it8q0,2772
184
- orchestrator/graphql/resolvers/product_block.py,sha256=Ker1CpxGab5h2BZujOHHwRUj8W4uphRr3WSpQGk2PnI,2939
185
- orchestrator/graphql/resolvers/resource_type.py,sha256=SREZXjkLYpuo4nCM8DqVeImIrZcP3xDiWr_gq4wWaxQ,2956
186
- orchestrator/graphql/resolvers/scheduled_tasks.py,sha256=QsnesRrj8ESuS9vPKG9DXYcG2Wfj9m5LWGeZgmc6hu8,1640
187
- orchestrator/graphql/resolvers/settings.py,sha256=xVYqxo-EWQ24F4hUHm9OZeN9vsqQXJzIJ1_HF4Ci9Cs,3777
188
- orchestrator/graphql/resolvers/subscription.py,sha256=57niFv-JCro_wm0peJ5Ne04F2WIPuJ-Lx2h8yd9qubA,6541
189
- orchestrator/graphql/resolvers/version.py,sha256=qgwe1msPOexeg3RHCscJ8s45vNfMhYh9ZKyCZ3MNw30,809
190
- orchestrator/graphql/resolvers/workflow.py,sha256=RKN-mI9Rg_4vVURXr943AHaftM6G3vpcRdeGgwy-uoc,2806
182
+ orchestrator/graphql/resolvers/helpers.py,sha256=RqQZrlH-YsxJ1qOnIMprrYR_K4gY2N8JFXM9PrmW15o,1215
183
+ orchestrator/graphql/resolvers/process.py,sha256=4pW80Ob8LfCqIXwTdVPE5KBpdoMGqqCVecl41HK5JEE,5034
184
+ orchestrator/graphql/resolvers/product.py,sha256=PvKPUBryO4V3NdtPzt6cSfZ3xHl8ftE8XCRDiAc4DwA,2790
185
+ orchestrator/graphql/resolvers/product_block.py,sha256=ugcrG1QyD-hjiOZdRA9EwIBkNSZbeXyXOiGaBEOlmMQ,2957
186
+ orchestrator/graphql/resolvers/resource_type.py,sha256=uELemhZPInapKhUO5oOg4fkX3v9gVij3ctD4IWg95Bo,2974
187
+ orchestrator/graphql/resolvers/scheduled_tasks.py,sha256=A_MxDp-v-gkxV9lZl_WHbeVdzWzqMDMnDwycQOC7x0c,1708
188
+ orchestrator/graphql/resolvers/settings.py,sha256=n3lLzP-aY19m9ZMDuBD0quSNstJZOMTFlk0-h0mppcU,3851
189
+ orchestrator/graphql/resolvers/subscription.py,sha256=XlA9EmSyI31djbdeCvm_uFs-8-JkU8mYCKUVI_r9euE,6694
190
+ orchestrator/graphql/resolvers/version.py,sha256=g1gLEicvXQK6iLks38hdDn8GK2k1s4cDhsa0nYXEa5E,883
191
+ orchestrator/graphql/resolvers/workflow.py,sha256=VmzE6GbkFxtfC57sP2pVg6pD1Ul10-NU3o-bxrlnHNs,2824
191
192
  orchestrator/graphql/schemas/__init__.py,sha256=dWG4DNzWq5akQ3v5tSAvT03HLxPWXa09Gx8rTz_MHmk,940
192
193
  orchestrator/graphql/schemas/customer.py,sha256=ZptVFG0qauZaoy29KDrh6k5xAnacNCTavmQrZMH8czc,147
193
194
  orchestrator/graphql/schemas/customer_description.py,sha256=fize71IMpkvk_rTzcqCYxazR5WBI652ZZ3eGvd8QqhQ,213
194
195
  orchestrator/graphql/schemas/errors.py,sha256=VRl-Zd1FHMnscyozhfxzqeEUZ0ERAWum_Y8YwjGxwmA,203
195
196
  orchestrator/graphql/schemas/fixed_input.py,sha256=1yqYHADQRgHz8OIP7ObYsPFS-gmzfkCvEO0a-KKf7zI,513
196
197
  orchestrator/graphql/schemas/helpers.py,sha256=Kpj4kIbmoKKN35bdgUSwQvGUIbeg7VJAVMEq65YS_ik,346
197
- orchestrator/graphql/schemas/process.py,sha256=wN4pKDuPbPHyyfGYaqFXMXxKTDm_zIwmyCOhSu5H1Iw,4978
198
+ orchestrator/graphql/schemas/process.py,sha256=APARniusSdqHkXann2oHp72PBE-nslQcLTQQaFFLiG4,4912
198
199
  orchestrator/graphql/schemas/product.py,sha256=vUCqcjrKBJj-VKSrMYPKzjmmxLMXL7alKTJ8UdUkhTg,4342
199
200
  orchestrator/graphql/schemas/product_block.py,sha256=Qk9cbA6vm7ZPrhdgPHatKRuy6TytBmxSr97McEOxAu8,2860
200
201
  orchestrator/graphql/schemas/resource_type.py,sha256=s5d_FwQXL2-Sc-IDUxTJun5qFQ4zOP4-XcHF9ql-t1g,898
@@ -272,54 +273,59 @@ orchestrator/schemas/process.py,sha256=UACBNt-4g4v9Y528u-gZ-Wk7YxwJHhnI4cEu5CtQm
272
273
  orchestrator/schemas/product.py,sha256=MhMCh058ZuS2RJq-wSmxIPUNlhQexxXIx3DSz2OmOh4,1570
273
274
  orchestrator/schemas/product_block.py,sha256=kCqvm6qadHpegMr9aWI_fYX-T7mS-5S-ldPxnGQZg7M,1519
274
275
  orchestrator/schemas/resource_type.py,sha256=VDju4XywcDDLxdpbWU62RTvR9QF8x_GRrpTlN_NE8uI,1064
275
- orchestrator/schemas/search.py,sha256=DOW-zwxr6VZVYbVsvft2mwFLv9M_nDegX33F6Bx1tJE,1548
276
+ orchestrator/schemas/search.py,sha256=d_Vs1qU9Z5zuXN4pDk6jrVwiUXRKZ93U-tHW5Zfrw-w,1546
277
+ orchestrator/schemas/search_requests.py,sha256=j2X98eLRTr_dYeGcIc78iPyKoYaAgvl1NQjYV4L1CGY,1925
276
278
  orchestrator/schemas/subscription.py,sha256=-jXyHZIed9Xlia18ksSDyenblNN6Q2yM2FlGELyJ458,3423
277
279
  orchestrator/schemas/subscription_descriptions.py,sha256=Ft_jw1U0bf9Z0U8O4OWfLlcl0mXCVT_qYVagBP3GbIQ,1262
278
280
  orchestrator/schemas/workflow.py,sha256=StVoRGyNT2iIeq3z8BIlTPt0bcafzbeYxXRrCucR6LU,2146
279
281
  orchestrator/search/__init__.py,sha256=2uhTQexKx-cdBP1retV3CYSNCs02s8WL3fhGvupRGZk,571
280
- orchestrator/search/export.py,sha256=_0ncVpTqN6AoQfW3WX0fWnDQX3hBz6ZGC31Beu4PVwQ,6678
281
- orchestrator/search/llm_migration.py,sha256=tJAfAoykMFIROQrKBKpAbDaGYDLKcmevKWjYrsBmuAY,6703
282
+ orchestrator/search/llm_migration.py,sha256=afDqdo5t-L6gLduKSSVKuAegznPdIsQn4YIoAAFraC8,6767
282
283
  orchestrator/search/agent/__init__.py,sha256=_O4DN0MSTUtr4olhyE0-2hsb7x3f_KURMCYjg8jV4QA,756
283
284
  orchestrator/search/agent/agent.py,sha256=iWa4_achqh5zRIfcJvjmY3hmDuFVGpV_PxjgttLdokU,2075
285
+ orchestrator/search/agent/handlers.py,sha256=z1KqeUUn7cYNBW39femwYnZOqRiYm1885Cx4TWVNyCY,4476
284
286
  orchestrator/search/agent/json_patch.py,sha256=_Z5ULhLyeuOuy-Gr_DJR4eA-wo9F78qySKUt5F_SQvQ,1892
285
- orchestrator/search/agent/prompts.py,sha256=6EPubiSLFyICIeinfVUF6miU1nS2QTAhqgzm-l5O3PI,5810
286
- orchestrator/search/agent/state.py,sha256=WhvZu7N0NhD1DD5mfZSUAzYN4mu8dDyvQ4Tz9I-hLtg,1364
287
- orchestrator/search/agent/tools.py,sha256=m4Krtb-Qmep-JkbJ9-RC7QqKa0CuQJM6-Z6_PN-b8HU,14706
287
+ orchestrator/search/agent/prompts.py,sha256=aNxdJz7M1RPg_Py5v3Wvc2Kzo_tshkfHqNlF6S7YQv4,6975
288
+ orchestrator/search/agent/state.py,sha256=YBrpHb8ok2RPwoLwBUWHYaGms_uj6nz51le2vbDjJwA,1113
289
+ orchestrator/search/agent/tools.py,sha256=hMovAKJ03EKsmGbdS363kbx1-BX4YJB6MsQUzZkEA38,17144
290
+ orchestrator/search/agent/validation.py,sha256=-U7g9Tgw6wH_tli0X0wrVKmiP9Id08sISq3kRrJjFNQ,2926
291
+ orchestrator/search/aggregations/__init__.py,sha256=Re5XDxvbRCT5DUFTQbHeDCyync1RL7yHh-D3Bm28CXg,921
292
+ orchestrator/search/aggregations/base.py,sha256=8zIdZx9cLxgFg6PePHzUNdMhHejPpb-hKL6lirDJlyQ,6916
288
293
  orchestrator/search/core/__init__.py,sha256=q5G0z3nKjIHKFs1PkEG3nvTUy3Wp4kCyBtCbqUITj3A,579
289
294
  orchestrator/search/core/embedding.py,sha256=n16H5fZRlfn91wI8PfZPa1R39HwQd8T1nwlDOzcOUBU,2823
290
295
  orchestrator/search/core/exceptions.py,sha256=S_ZMEhrqsQBVqJ559FQ5J6tZU6BYLiU65AGWgSvgv_k,1159
291
- orchestrator/search/core/types.py,sha256=0U_m4ZmPwvL77hIx9yk7UyvkE8HoiRvEnGdY4mDLzCo,8853
296
+ orchestrator/search/core/types.py,sha256=eEar-1MFKiOqagKp9e2DLEZtGQQGQR_Ia7fiuRzIVoc,8953
292
297
  orchestrator/search/core/validators.py,sha256=zktY5A3RTBmfdARJoxoz9rnnyTZj7L30Kbmh9UTQz2o,1204
293
298
  orchestrator/search/docs/index.md,sha256=zKzE2fbtHDfYTKaHg628wAsqCTOJ5yFUWV0ucFH3pAg,863
294
299
  orchestrator/search/docs/running_local_text_embedding_inference.md,sha256=OR0NVZMb8DqpgXYxlwDUrJwfRk0bYOk1-LkDMqsV6bU,1327
295
- orchestrator/search/filters/__init__.py,sha256=Yutr21lv8RtZf5OKaBozlYufgmmV2QHuzAPPjvUamLE,1222
300
+ orchestrator/search/filters/__init__.py,sha256=pmnHyq5SrqxS6eEiyhSIify776W9BIZ0gjOZFuYZ0nU,1335
296
301
  orchestrator/search/filters/base.py,sha256=lUr0eW0zi4oIMVUHuRD3GAQ9xEbHiFUl_EfAI6ABPVo,12456
297
302
  orchestrator/search/filters/date_filters.py,sha256=0a6nbUTK647_Qf4XXZMLDvBLVjF5Qqy9eJ-9SrTGaGg,3040
298
- orchestrator/search/filters/definitions.py,sha256=wl2HiXlTWXQN4JmuSq2SBuhTMvyIeonTtUZoCrJAK6M,4093
303
+ orchestrator/search/filters/definitions.py,sha256=k30Dp1bEr3CWMeuIcF1wPgmmF3rxI9Urx-sCaPfaE3c,4607
299
304
  orchestrator/search/filters/ltree_filters.py,sha256=1OOmM5K90NsGBQmTqyoDlphdAOGd9r2rmz1rNItm8yk,2341
300
- orchestrator/search/filters/numeric_filter.py,sha256=lcOAOpPNTwA0SW8QPiMOs1oKTYZLwGDQSrwFydXgMUU,2774
305
+ orchestrator/search/filters/numeric_filter.py,sha256=do52w5Dmb5Rt4ipfX1iEObNcdymbWHtgS2HI1Otq-JQ,2771
301
306
  orchestrator/search/indexing/__init__.py,sha256=Or78bizNPiuNOgwLGJQ0mspCF1G_gSe5C9Ap7qi0MZk,662
302
307
  orchestrator/search/indexing/indexer.py,sha256=2qqDe6IlKfz1exh0xLBmpPdkTqbapLnTJORZneM6tmw,15320
303
308
  orchestrator/search/indexing/registry.py,sha256=N4YOUhNJfY6iBwPnn76tDcZaOVYJMA2SxwWhdBE85Xs,3716
304
309
  orchestrator/search/indexing/tasks.py,sha256=vmS1nnprPF74yitS0xGpP1dhSDis2nekMYF0v_jduDE,2478
305
310
  orchestrator/search/indexing/traverse.py,sha256=NKkKSri-if1d1vwzTQlDCF0hvBdB2IbWWuMdPrQ78Jg,14330
306
- orchestrator/search/retrieval/__init__.py,sha256=WpbC65DrI1AlNPvp5QDZXUZzGnzZ8Av0-9fH95eWvs0,763
307
- orchestrator/search/retrieval/builder.py,sha256=af_m4I-p_8eJ85t2B99jxecYlzFaY4F0CZwh4YFf_Us,4669
308
- orchestrator/search/retrieval/engine.py,sha256=RjaH70ChVU2etx5I6PuePcwbVGhxVVw_zG2ZlOviOPQ,7635
309
- orchestrator/search/retrieval/exceptions.py,sha256=oHoLGLLxxmVcV-W36uK0V-Pn4vf_iw6hajpQbap3NqI,3588
310
- orchestrator/search/retrieval/pagination.py,sha256=mJMesuHaxYvJggy8MsxRmfof_D-LuDVc_lGQ_jhqWkQ,3148
311
- orchestrator/search/retrieval/query_state.py,sha256=Gxhb7JcS40Qv2w9wvCp6_CPokGOQoxByyjc-AhK1LRI,2301
312
- orchestrator/search/retrieval/utils.py,sha256=svhF9YfMClq2MVPArS3ir3pg5_e_bremquv_l6tTsOQ,4597
313
- orchestrator/search/retrieval/validation.py,sha256=AjhttVJWlZDaT1_pUL_LaypQV11U21JpTCE4OwnpoqA,5849
311
+ orchestrator/search/query/__init__.py,sha256=nCjvK_n2WQdV_ACrncFXEfnvLcHtuI__J7KLlFIaQvo,2437
312
+ orchestrator/search/query/builder.py,sha256=kgnJ93TOCm8UTL5k09nWLsG4NXAlvFFa65gbciOwZ8E,10153
313
+ orchestrator/search/query/engine.py,sha256=TFdV_sSoSXCSDSpyhVA2S6YaJysDSW2WtPj7duAyomk,5745
314
+ orchestrator/search/query/exceptions.py,sha256=DrkNzXVbQAOi28FTHKimf_eTrXmhYwXrH986QhfQLPU,4941
315
+ orchestrator/search/query/export.py,sha256=_0ncVpTqN6AoQfW3WX0fWnDQX3hBz6ZGC31Beu4PVwQ,6678
316
+ orchestrator/search/query/mixins.py,sha256=BdVDzCOFDXT6N9LI_WrbVzGrk61UNplX-UZPvD0rEV0,3019
317
+ orchestrator/search/query/queries.py,sha256=j1uKSQgF_ifVaDJaxjs4h2z48KqGVEIKCXOoJ7Ur9Mk,3805
318
+ orchestrator/search/query/results.py,sha256=8k3o7F5EESuNOdNRPsmv0klPAG9YlPisCR4iGtewiXg,8662
319
+ orchestrator/search/query/state.py,sha256=fMSBJs39kZTkpDE2T4h4x0x-51GqUvzAuePg2YUbO6I,3220
320
+ orchestrator/search/query/validation.py,sha256=m0xJ71A0Qa5hm8b71zKRjSVpPrnkG7LbqPu4lv_GboI,8260
321
+ orchestrator/search/retrieval/__init__.py,sha256=q5G0z3nKjIHKFs1PkEG3nvTUy3Wp4kCyBtCbqUITj3A,579
322
+ orchestrator/search/retrieval/pagination.py,sha256=kcUzq1QQk4GrZq02M4hsKwAelUo1qDeCqsXImLUK6DA,3006
314
323
  orchestrator/search/retrieval/retrievers/__init__.py,sha256=1bGmbae0GYRM6e1vxf0ww79NaTSmfOMe9S0pPVmh3CM,897
315
- orchestrator/search/retrieval/retrievers/base.py,sha256=GyVbFVsZwjolyVfgGv3kYD22dxRhvRbUI7h9BjeK1DU,4174
324
+ orchestrator/search/retrieval/retrievers/base.py,sha256=Xfjo-LD_fltKy0xhBBUSsmm2v2TNygDotWQ0wTTyvVE,4155
316
325
  orchestrator/search/retrieval/retrievers/fuzzy.py,sha256=PLp_ANRLzmtGQP1t9X4jt43_JLKDnOxWU2xqlexSH1U,3779
317
326
  orchestrator/search/retrieval/retrievers/hybrid.py,sha256=l-7J4qct0h28wSi0KvdFJw2lyh3jyobbrCbg0PuX-4I,11141
318
327
  orchestrator/search/retrieval/retrievers/semantic.py,sha256=36ky_A_LNWs13IYe809qy1RPrd0Fab-G-9pf2ZDARhA,3905
319
328
  orchestrator/search/retrieval/retrievers/structured.py,sha256=13TxC52fpNGXHnPX40J2GczRYFk8LAvWn2a0HWZCd2Q,1426
320
- orchestrator/search/schemas/__init__.py,sha256=q5G0z3nKjIHKFs1PkEG3nvTUy3Wp4kCyBtCbqUITj3A,579
321
- orchestrator/search/schemas/parameters.py,sha256=rrRLF_3p41SDEzX5yt-IPQWawGAcSzpeOVROhqulnbc,4834
322
- orchestrator/search/schemas/results.py,sha256=5UU4mmTrIu--RDW4nrl6_EpdYCMf_S-kj0OyR0aaOHQ,2096
323
329
  orchestrator/services/__init__.py,sha256=GyHNfEFCGKQwRiN6rQmvSRH2iYX7npjMZn97n8XzmLU,571
324
330
  orchestrator/services/fixed_inputs.py,sha256=kyz7s2HLzyDulvcq-ZqefTw1om86COvyvTjz0_5CmgI,876
325
331
  orchestrator/services/input_state.py,sha256=6BZOpb3cHpO18K-XG-3QUIV9pIM25_ufdODrp5CmXG4,2390
@@ -372,8 +378,8 @@ orchestrator/workflows/tasks/cleanup_tasks_log.py,sha256=BfWYbPXhnLAHUJ0mlODDnjZ
372
378
  orchestrator/workflows/tasks/resume_workflows.py,sha256=T3iobSJjVgiupe0rClD34kUZ7KF4pL5yK2AVeRLZog8,4313
373
379
  orchestrator/workflows/tasks/validate_product_type.py,sha256=lo2TX_MZOfcOmYFjLyD82FrJ5AAN3HOsE6BhDVFuy9Q,3210
374
380
  orchestrator/workflows/tasks/validate_products.py,sha256=GZJBoFF-WMphS7ghMs2-gqvV2iL1F0POhk0uSNt93n0,8510
375
- orchestrator/workflows/translations/en-GB.json,sha256=ST53HxkphFLTMjFHonykDBOZ7-P_KxksktZU3GbxLt0,846
376
- orchestrator_core-4.6.1.dist-info/licenses/LICENSE,sha256=b-aA5OZQuuBATmLKo_mln8CQrDPPhg3ghLzjPjLn4Tg,11409
377
- orchestrator_core-4.6.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
378
- orchestrator_core-4.6.1.dist-info/METADATA,sha256=vD8LAwJ3cF18I_90KA-36bLcJ4jz_LiJOxwMVrb68bM,6351
379
- orchestrator_core-4.6.1.dist-info/RECORD,,
381
+ orchestrator/workflows/translations/en-GB.json,sha256=Gc5gy_RghZOeSNcJIntAsz_7DsCg8n_vzoHBPXxCn_U,908
382
+ orchestrator_core-4.6.3.dist-info/licenses/LICENSE,sha256=b-aA5OZQuuBATmLKo_mln8CQrDPPhg3ghLzjPjLn4Tg,11409
383
+ orchestrator_core-4.6.3.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
384
+ orchestrator_core-4.6.3.dist-info/METADATA,sha256=nw7A7L5C76TZYOZ8NycRKwxH13tMucr4JkghhrztitM,6416
385
+ orchestrator_core-4.6.3.dist-info/RECORD,,
@@ -1,127 +0,0 @@
1
- # Copyright 2019-2025 SURF, GÉANT.
2
- # Licensed under the Apache License, Version 2.0 (the "License");
3
- # you may not use this file except in compliance with the License.
4
- # You may obtain a copy of the License at
5
- #
6
- # http://www.apache.org/licenses/LICENSE-2.0
7
- #
8
- # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an "AS IS" BASIS,
10
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- # See the License for the specific language governing permissions and
12
- # limitations under the License.
13
-
14
- from collections import defaultdict
15
- from typing import Sequence
16
-
17
- from sqlalchemy import Select, String, cast, func, select
18
- from sqlalchemy.engine import Row
19
-
20
- from orchestrator.db.models import AiSearchIndex
21
- from orchestrator.search.core.types import EntityType, FieldType, FilterOp, UIType
22
- from orchestrator.search.filters import LtreeFilter
23
- from orchestrator.search.schemas.parameters import BaseSearchParameters
24
- from orchestrator.search.schemas.results import ComponentInfo, LeafInfo
25
-
26
-
27
- def create_path_autocomplete_lquery(prefix: str) -> str:
28
- """Create the lquery pattern for a multi-level path autocomplete search."""
29
- return f"{prefix}*.*"
30
-
31
-
32
- def build_candidate_query(params: BaseSearchParameters) -> Select:
33
- """Build the base query for retrieving candidate entities.
34
-
35
- Constructs a `SELECT` statement that retrieves distinct `entity_id` values
36
- from the index table for the given entity type, applying any structured
37
- filters from the provided search parameters.
38
-
39
- Args:
40
- params (BaseSearchParameters): The search parameters containing the entity type and optional filters.
41
-
42
- Returns:
43
- Select: The SQLAlchemy `Select` object representing the query.
44
- """
45
-
46
- stmt = (
47
- select(AiSearchIndex.entity_id, AiSearchIndex.entity_title)
48
- .where(AiSearchIndex.entity_type == params.entity_type.value)
49
- .distinct()
50
- )
51
-
52
- if params.filters is not None:
53
- entity_id_col = AiSearchIndex.entity_id
54
- stmt = stmt.where(
55
- params.filters.to_expression(
56
- entity_id_col,
57
- entity_type_value=params.entity_type.value,
58
- )
59
- )
60
-
61
- return stmt
62
-
63
-
64
- def build_paths_query(entity_type: EntityType, prefix: str | None = None, q: str | None = None) -> Select:
65
- """Build the query for retrieving paths and their value types for leaves/components processing."""
66
- stmt = select(AiSearchIndex.path, AiSearchIndex.value_type).where(AiSearchIndex.entity_type == entity_type.value)
67
-
68
- if prefix:
69
- lquery_pattern = create_path_autocomplete_lquery(prefix)
70
- ltree_filter = LtreeFilter(op=FilterOp.MATCHES_LQUERY, value=lquery_pattern)
71
- stmt = stmt.where(ltree_filter.to_expression(AiSearchIndex.path, path=""))
72
-
73
- stmt = stmt.group_by(AiSearchIndex.path, AiSearchIndex.value_type)
74
-
75
- if q:
76
- score = func.similarity(cast(AiSearchIndex.path, String), q)
77
- stmt = stmt.order_by(score.desc(), AiSearchIndex.path)
78
- else:
79
- stmt = stmt.order_by(AiSearchIndex.path)
80
-
81
- return stmt
82
-
83
-
84
- def process_path_rows(rows: Sequence[Row]) -> tuple[list[LeafInfo], list[ComponentInfo]]:
85
- """Process query results to extract leaves and components information.
86
-
87
- Parameters
88
- ----------
89
- rows : Sequence[Row]
90
- Database rows containing path and value_type information
91
-
92
- Returns:
93
- -------
94
- tuple[list[LeafInfo], list[ComponentInfo]]
95
- Processed leaves and components
96
- """
97
- leaves_dict: dict[str, set[UIType]] = defaultdict(set)
98
- leaves_paths_dict: dict[str, set[str]] = defaultdict(set)
99
- components_set: set[str] = set()
100
-
101
- for row in rows:
102
- path, value_type = row
103
-
104
- path_str = str(path)
105
- path_segments = path_str.split(".")
106
-
107
- # Remove numeric segments
108
- clean_segments = [seg for seg in path_segments if not seg.isdigit()]
109
-
110
- if clean_segments:
111
- # Last segment is a leaf
112
- leaf_name = clean_segments[-1]
113
- ui_type = UIType.from_field_type(FieldType(value_type))
114
- leaves_dict[leaf_name].add(ui_type)
115
- leaves_paths_dict[leaf_name].add(path_str)
116
-
117
- # All segments except the first/last are components
118
- for component in clean_segments[1:-1]:
119
- components_set.add(component)
120
-
121
- leaves = [
122
- LeafInfo(name=leaf, ui_types=list(types), paths=sorted(leaves_paths_dict[leaf]))
123
- for leaf, types in leaves_dict.items()
124
- ]
125
- components = [ComponentInfo(name=component, ui_types=[UIType.COMPONENT]) for component in sorted(components_set)]
126
-
127
- return leaves, components
@@ -1,197 +0,0 @@
1
- # Copyright 2019-2025 SURF, GÉANT.
2
- # Licensed under the Apache License, Version 2.0 (the "License");
3
- # you may not use this file except in compliance with the License.
4
- # You may obtain a copy of the License at
5
- #
6
- # http://www.apache.org/licenses/LICENSE-2.0
7
- #
8
- # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an "AS IS" BASIS,
10
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- # See the License for the specific language governing permissions and
12
- # limitations under the License.
13
-
14
- from collections.abc import Sequence
15
-
16
- import structlog
17
- from sqlalchemy.engine.row import RowMapping
18
- from sqlalchemy.orm import Session
19
-
20
- from orchestrator.search.core.embedding import QueryEmbedder
21
- from orchestrator.search.core.types import FilterOp, SearchMetadata
22
- from orchestrator.search.filters import FilterTree, LtreeFilter
23
- from orchestrator.search.schemas.parameters import BaseSearchParameters
24
- from orchestrator.search.schemas.results import MatchingField, SearchResponse, SearchResult
25
-
26
- from .builder import build_candidate_query
27
- from .pagination import PageCursor
28
- from .query_state import SearchQueryState
29
- from .retrievers import Retriever
30
- from .utils import generate_highlight_indices
31
-
32
- logger = structlog.get_logger(__name__)
33
-
34
-
35
- def _format_response(
36
- db_rows: Sequence[RowMapping], search_params: BaseSearchParameters, metadata: SearchMetadata
37
- ) -> SearchResponse:
38
- """Format database query results into a `SearchResponse`.
39
-
40
- Converts raw SQLAlchemy `RowMapping` objects into `SearchResult` instances,
41
- including highlight metadata if present in the database results.
42
-
43
- Args:
44
- db_rows (Sequence[RowMapping]): The rows returned from the executed SQLAlchemy query.
45
- search_params (BaseSearchParameters): The search parameters, including query text and filters.
46
- metadata (SearchMetadata): Metadata about the search execution.
47
-
48
- Returns:
49
- SearchResponse: A list of `SearchResult` objects containing entity IDs, scores,
50
- and optional highlight information.
51
- """
52
-
53
- if not db_rows:
54
- return SearchResponse(results=[], metadata=metadata)
55
-
56
- user_query = search_params.query
57
-
58
- results = []
59
- for row in db_rows:
60
- matching_field = None
61
-
62
- if (
63
- user_query
64
- and (text := row.get(Retriever.HIGHLIGHT_TEXT_LABEL))
65
- and (path := row.get(Retriever.HIGHLIGHT_PATH_LABEL))
66
- ):
67
- if not isinstance(text, str):
68
- text = str(text)
69
- if not isinstance(path, str):
70
- path = str(path)
71
-
72
- highlight_indices = generate_highlight_indices(text, user_query) or None
73
- matching_field = MatchingField(text=text, path=path, highlight_indices=highlight_indices)
74
-
75
- elif not user_query and search_params.filters and metadata.search_type == "structured":
76
- # Structured search (filter-only)
77
- matching_field = _extract_matching_field_from_filters(search_params.filters)
78
-
79
- entity_title = row.get("entity_title", "")
80
- if not isinstance(entity_title, str):
81
- entity_title = str(entity_title) if entity_title is not None else ""
82
-
83
- results.append(
84
- SearchResult(
85
- entity_id=str(row.entity_id),
86
- entity_type=search_params.entity_type,
87
- entity_title=entity_title,
88
- score=row.score,
89
- perfect_match=row.get("perfect_match", 0),
90
- matching_field=matching_field,
91
- )
92
- )
93
- return SearchResponse(results=results, metadata=metadata)
94
-
95
-
96
- def _extract_matching_field_from_filters(filters: FilterTree) -> MatchingField | None:
97
- """Extract the first path filter to use as matching field for structured searches."""
98
- leaves = filters.get_all_leaves()
99
- if len(leaves) != 1:
100
- return None
101
-
102
- pf = leaves[0]
103
-
104
- if isinstance(pf.condition, LtreeFilter):
105
- op = pf.condition.op
106
- # Prefer the original component/pattern (validator may set path="*" and move the value)
107
- display = str(getattr(pf.condition, "value", "") or pf.path)
108
-
109
- # There can be no match for abscence.
110
- if op == FilterOp.NOT_HAS_COMPONENT:
111
- return None
112
-
113
- return MatchingField(text=display, path=display, highlight_indices=[(0, len(display))])
114
-
115
- # Everything thats not Ltree
116
- val = getattr(pf.condition, "value", "")
117
- text = "" if val is None else str(val)
118
- return MatchingField(text=text, path=pf.path, highlight_indices=[(0, len(text))])
119
-
120
-
121
- async def _execute_search_internal(
122
- search_params: BaseSearchParameters,
123
- db_session: Session,
124
- limit: int,
125
- cursor: PageCursor | None = None,
126
- query_embedding: list[float] | None = None,
127
- ) -> SearchResponse:
128
- """Internal function to execute search with specified parameters.
129
-
130
- Args:
131
- search_params: The search parameters specifying vector, fuzzy, or filter criteria.
132
- db_session: The active SQLAlchemy session for executing the query.
133
- limit: Maximum number of results to return.
134
- cursor: Optional pagination cursor.
135
- query_embedding: Optional pre-computed query embedding to use instead of generating a new one.
136
-
137
- Returns:
138
- SearchResponse with results and embedding (for internal use).
139
- """
140
- if not search_params.vector_query and not search_params.filters and not search_params.fuzzy_term:
141
- logger.warning("No search criteria provided (vector_query, fuzzy_term, or filters).")
142
- return SearchResponse(results=[], metadata=SearchMetadata.empty())
143
-
144
- candidate_query = build_candidate_query(search_params)
145
-
146
- if search_params.vector_query and not query_embedding:
147
-
148
- query_embedding = await QueryEmbedder.generate_for_text_async(search_params.vector_query)
149
-
150
- retriever = await Retriever.route(search_params, cursor, query_embedding)
151
- logger.debug("Using retriever", retriever_type=retriever.__class__.__name__)
152
-
153
- final_stmt = retriever.apply(candidate_query)
154
- final_stmt = final_stmt.limit(limit)
155
- logger.debug(final_stmt)
156
- result = db_session.execute(final_stmt).mappings().all()
157
-
158
- response = _format_response(result, search_params, retriever.metadata)
159
- # Store embedding in response for agent to save to DB
160
- response.query_embedding = query_embedding
161
- return response
162
-
163
-
164
- async def execute_search(
165
- search_params: BaseSearchParameters,
166
- db_session: Session,
167
- cursor: PageCursor | None = None,
168
- query_embedding: list[float] | None = None,
169
- ) -> SearchResponse:
170
- """Execute a search and return ranked results."""
171
- return await _execute_search_internal(search_params, db_session, search_params.limit, cursor, query_embedding)
172
-
173
-
174
- async def execute_search_for_export(
175
- query_state: SearchQueryState,
176
- db_session: Session,
177
- ) -> list[dict]:
178
- """Execute a search for export and fetch flattened entity data.
179
-
180
- Args:
181
- query_state: Query state containing parameters and query_embedding.
182
- db_session: The active SQLAlchemy session for executing the query.
183
-
184
- Returns:
185
- List of flattened entity records suitable for export.
186
- """
187
- from orchestrator.search.export import fetch_export_data
188
-
189
- search_response = await _execute_search_internal(
190
- search_params=query_state.parameters,
191
- db_session=db_session,
192
- limit=query_state.parameters.export_limit,
193
- query_embedding=query_state.query_embedding,
194
- )
195
-
196
- entity_ids = [res.entity_id for res in search_response.results]
197
- return fetch_export_data(query_state.parameters.entity_type, entity_ids)
@@ -1,133 +0,0 @@
1
- # Copyright 2019-2025 SURF, GÉANT.
2
- # Licensed under the Apache License, Version 2.0 (the "License");
3
- # you may not use this file except in compliance with the License.
4
- # You may obtain a copy of the License at
5
- #
6
- # http://www.apache.org/licenses/LICENSE-2.0
7
- #
8
- # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an "AS IS" BASIS,
10
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- # See the License for the specific language governing permissions and
12
- # limitations under the License.
13
-
14
- import uuid
15
- from typing import Any, ClassVar, Literal
16
-
17
- from pydantic import BaseModel, ConfigDict, Field, TypeAdapter
18
-
19
- from orchestrator.search.core.types import ActionType, EntityType
20
- from orchestrator.search.filters import FilterTree
21
-
22
-
23
- class BaseSearchParameters(BaseModel):
24
- """Base model with common search parameters."""
25
-
26
- DEFAULT_EXPORT_LIMIT: ClassVar[int] = 1000
27
- MAX_EXPORT_LIMIT: ClassVar[int] = 10000
28
-
29
- action: ActionType = Field(default=ActionType.SELECT, description="The action to perform.")
30
- entity_type: EntityType
31
-
32
- filters: FilterTree | None = Field(default=None, description="A list of structured filters to apply to the search.")
33
-
34
- query: str | None = Field(
35
- default=None, description="Unified search query - will be processed into vector_query and/or fuzzy_term"
36
- )
37
-
38
- limit: int = Field(default=10, ge=1, le=30, description="Maximum number of search results to return.")
39
- export_limit: int = Field(
40
- default=DEFAULT_EXPORT_LIMIT, ge=1, le=MAX_EXPORT_LIMIT, description="Maximum number of results to export."
41
- )
42
- model_config = ConfigDict(extra="forbid")
43
-
44
- @classmethod
45
- def create(cls, **kwargs: Any) -> "SearchParameters":
46
- """Create the correct search parameter subclass instance based on entity_type."""
47
- from orchestrator.search.schemas.parameters import SearchParameters
48
-
49
- adapter: TypeAdapter = TypeAdapter(SearchParameters)
50
- return adapter.validate_python(kwargs)
51
-
52
- @property
53
- def vector_query(self) -> str | None:
54
- """Extract vector query from unified query field."""
55
- if not self.query:
56
- return None
57
- try:
58
- uuid.UUID(self.query)
59
- return None # It's a UUID, so disable vector search.
60
- except ValueError:
61
- return self.query
62
-
63
- @property
64
- def fuzzy_term(self) -> str | None:
65
- """Extract fuzzy term from unified query field."""
66
- if not self.query:
67
- return None
68
-
69
- words = self.query.split()
70
- # Only use fuzzy for single words
71
- # otherwise, trigram operator filters out too much.
72
- return self.query if len(words) == 1 else None
73
-
74
-
75
- class SubscriptionSearchParameters(BaseSearchParameters):
76
- entity_type: Literal[EntityType.SUBSCRIPTION] = Field(
77
- default=EntityType.SUBSCRIPTION, description="The type of entity to search."
78
- )
79
- model_config = ConfigDict(
80
- json_schema_extra={
81
- "title": "SearchSubscriptions",
82
- "description": "Search subscriptions based on specific criteria.",
83
- "examples": [
84
- {
85
- "filters": {
86
- "op": "AND",
87
- "children": [
88
- {"path": "subscription.status", "condition": {"op": "eq", "value": "provisioning"}},
89
- {"path": "subscription.end_date", "condition": {"op": "gte", "value": "2025-01-01"}},
90
- ],
91
- }
92
- }
93
- ],
94
- }
95
- )
96
-
97
-
98
- class ProductSearchParameters(BaseSearchParameters):
99
- entity_type: Literal[EntityType.PRODUCT] = Field(
100
- default=EntityType.PRODUCT, description="The type of entity to search."
101
- )
102
- model_config = ConfigDict(
103
- json_schema_extra={
104
- "title": "SearchProducts",
105
- "description": "Search products based on specific criteria.",
106
- "examples": [
107
- {
108
- "filters": [
109
- {"path": "product.product_type", "condition": {"op": "eq", "value": "Shop"}},
110
- ]
111
- }
112
- ],
113
- }
114
- )
115
-
116
-
117
- class WorkflowSearchParameters(BaseSearchParameters):
118
- entity_type: Literal[EntityType.WORKFLOW] = Field(
119
- default=EntityType.WORKFLOW, description="The type of entity to search."
120
- )
121
-
122
-
123
- class ProcessSearchParameters(BaseSearchParameters):
124
- """Search parameters specifically for PROCESS entities."""
125
-
126
- entity_type: Literal[EntityType.PROCESS] = Field(
127
- default=EntityType.PROCESS, description="The type of entity to search."
128
- )
129
-
130
-
131
- SearchParameters = (
132
- SubscriptionSearchParameters | ProductSearchParameters | WorkflowSearchParameters | ProcessSearchParameters
133
- )