agentengine-sdk-python 0.8.2__py3-none-any.whl → 0.8.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 (250) hide show
  1. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/METADATA +18 -25
  2. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/RECORD +224 -169
  3. ksadk/_build_provenance.json +1 -0
  4. ksadk/agui/_agent_helpers.py +4 -0
  5. ksadk/api/client.py +3 -0
  6. ksadk/builders/managed_runtime_builder.py +3 -0
  7. ksadk/cli/__init__.py +6 -0
  8. ksadk/cli/cmd_plugin.py +657 -0
  9. ksadk/codex/runtime.py +50 -8
  10. ksadk/configs/env_registry.py +31 -3
  11. ksadk/configs/settings.py +9 -0
  12. ksadk/context_engine/contributors.py +73 -8
  13. ksadk/conversations/__init__.py +19 -0
  14. ksadk/conversations/context.py +104 -24
  15. ksadk/conversations/contracts.py +266 -0
  16. ksadk/conversations/message_projection.py +19 -1
  17. ksadk/conversations/projector.py +616 -0
  18. ksadk/conversations/reducer.py +98 -0
  19. ksadk/events/_v1_compat/projection.py +2 -0
  20. ksadk/events/adapters/codex.py +190 -0
  21. ksadk/harness/__init__.py +45 -35
  22. ksadk/harness/runtime.py +60 -1
  23. ksadk/kernel/contract_fingerprints.py +5 -4
  24. ksadk/kernel/contracts.py +8 -0
  25. ksadk/kernel/control.py +1 -0
  26. ksadk/kernel/ingress.py +21 -0
  27. ksadk/kernel/memory_store.py +1 -0
  28. ksadk/kernel/postgres_store.py +1 -0
  29. ksadk/kernel/sqlite_store.py +1 -0
  30. ksadk/kernel/worker.py +11 -0
  31. ksadk/memory/providers/local_sqlite.py +7 -0
  32. ksadk/plugins/__init__.py +167 -0
  33. ksadk/plugins/bridges/__init__.py +45 -0
  34. ksadk/plugins/bridges/codex.py +552 -0
  35. ksadk/plugins/bridges/dsh.py +1116 -0
  36. ksadk/plugins/builtins.py +747 -0
  37. ksadk/plugins/bundle.py +246 -0
  38. ksadk/plugins/bundle_security.py +167 -0
  39. ksadk/plugins/composition.py +529 -0
  40. ksadk/plugins/context_contributor.py +437 -0
  41. ksadk/plugins/contracts.py +451 -0
  42. ksadk/plugins/dsh_toolchain.py +935 -0
  43. ksadk/plugins/ecosystem_bridge.py +1105 -0
  44. ksadk/plugins/ecosystem_probe.py +191 -0
  45. ksadk/plugins/host.py +724 -0
  46. ksadk/plugins/providers/__init__.py +85 -0
  47. ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
  48. ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
  49. ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
  50. ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
  51. ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
  52. ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
  53. ksadk/plugins/providers/codex.py +722 -0
  54. ksadk/plugins/providers/codex_dsh.py +83 -0
  55. ksadk/plugins/providers/dsh.py +951 -0
  56. ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
  57. ksadk/plugins/providers/harness.py +627 -0
  58. ksadk/plugins/providers/harness_dsh.py +91 -0
  59. ksadk/plugins/providers/legacy.py +215 -0
  60. ksadk/plugins/providers/legacy_catalog.py +100 -0
  61. ksadk/plugins/providers/shipped_dsh.py +370 -0
  62. ksadk/plugins/resolver.py +331 -0
  63. ksadk/plugins/subagent_providers/__init__.py +12 -0
  64. ksadk/plugins/subagent_providers/codex.py +443 -0
  65. ksadk/plugins/subagents.py +333 -0
  66. ksadk/runtime/_runner_adapter/stream_mapping.py +51 -42
  67. ksadk/runtime/adapter.py +1 -0
  68. ksadk/runtime/factory.py +76 -2
  69. ksadk/runtime/framework_adapters.py +18 -0
  70. ksadk/runtime/runner_adapter.py +5 -0
  71. ksadk/sandbox/__init__.py +2 -1
  72. ksadk/sandbox/factory.py +72 -0
  73. ksadk/scheduler/__init__.py +18 -0
  74. ksadk/scheduler/calendar.py +102 -0
  75. ksadk/scheduler/contracts.py +254 -0
  76. ksadk/scheduler/dispatcher.py +129 -0
  77. ksadk/scheduler/engine.py +416 -0
  78. ksadk/scheduler/sqlite_store.py +563 -0
  79. ksadk/server/static/assets/{ArtifactsPanel-DSU1sWD_.js → ArtifactsPanel-10GPXIJ6.js} +1 -1
  80. ksadk/server/static/assets/{CodeBlock-DOH6MVcn.js → CodeBlock-BXk1l-G1.js} +1 -1
  81. ksadk/server/static/assets/{MathMessageMarkdown-BL8my1R2.js → MathMessageMarkdown-D9uB55Oh.js} +1 -1
  82. ksadk/server/static/assets/{MermaidBlock-Dz4IP-Tx.js → MermaidBlock--OEYoXIJ.js} +6 -6
  83. ksadk/server/static/assets/{NativeTerminalPanel-DUrK0JpZ.js → NativeTerminalPanel-DrEe1syq.js} +1 -1
  84. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-g20pFzNV.js → abnfDiagram-VCTEODGH-eeTFJLvo.js} +1 -1
  85. ksadk/server/static/assets/{arc-C4FzinUA.js → arc-S3ZNbIAd.js} +1 -1
  86. ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +1 -0
  87. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-DpIqL5h4.js → architectureDiagram-5GKGNRK7-CRjgEJDX.js} +1 -1
  88. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-BjkljTNz.js → blockDiagram-NRAW4CY4-C7bsBoNH.js} +1 -1
  89. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-Dk_ieq2X.js → c4Diagram-UCG6FXSJ-BX3c33Ob.js} +1 -1
  90. ksadk/server/static/assets/channel-s354Yo6o.js +1 -0
  91. ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +1 -0
  92. ksadk/server/static/assets/{chunk-5VM5RSS4-BVHAchFb.js → chunk-5VM5RSS4-bZ7ws-8m.js} +1 -1
  93. ksadk/server/static/assets/{chunk-F27PBJKO-C-ipQzuS.js → chunk-F27PBJKO-D2r0pvhY.js} +1 -1
  94. ksadk/server/static/assets/{chunk-G27WJ6UU-C2EyJbIK.js → chunk-G27WJ6UU-CZwF3oUP.js} +1 -1
  95. ksadk/server/static/assets/{chunk-JWPE2WC7-vYvVJb_M.js → chunk-JWPE2WC7-DigFYCML.js} +1 -1
  96. ksadk/server/static/assets/{chunk-LCL6LL3I-BcI6ysPT.js → chunk-LCL6LL3I-CnorGV5q.js} +1 -1
  97. ksadk/server/static/assets/{chunk-POPQ4Y6H-C030x_Z1.js → chunk-POPQ4Y6H-CexntQA-.js} +1 -1
  98. ksadk/server/static/assets/{chunk-RHFEMEQ7-yyGpsz4n.js → chunk-RHFEMEQ7-CHTC7UxA.js} +1 -1
  99. ksadk/server/static/assets/{chunk-SVP7TREG-BLTlmMU7.js → chunk-SVP7TREG-BC1EWt_-.js} +1 -1
  100. ksadk/server/static/assets/{chunk-XXDRQBXY-C_32ArgP.js → chunk-XXDRQBXY-BTG24xN0.js} +1 -1
  101. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +1 -0
  102. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +1 -0
  103. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-9YQYwdl0.js → cose-bilkent-JH36ORCC-CkonRdAS.js} +1 -1
  104. ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +1 -0
  105. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-ErLF5N13.js → cynefinDiagram-5FMLGOSQ-DEOCBe15.js} +1 -1
  106. ksadk/server/static/assets/{dagre-3AP2YEHR-DFiQF-6f.js → dagre-3AP2YEHR-DBThPuLa.js} +1 -1
  107. ksadk/server/static/assets/{dagre-BuhGnRI1.js → dagre-ClTPrTht.js} +1 -1
  108. ksadk/server/static/assets/{diagram-S7CK7UJ4-Bt1v8-GC.js → diagram-S7CK7UJ4-DsZHrnpJ.js} +1 -1
  109. ksadk/server/static/assets/{diagram-UQ7AKVKN-DSCxJdBK.js → diagram-UQ7AKVKN-BJR4nhVr.js} +1 -1
  110. ksadk/server/static/assets/{diagram-VSXAHHWV-DHfYwp_9.js → diagram-VSXAHHWV-xzcERX0a.js} +1 -1
  111. ksadk/server/static/assets/{diagram-VX7I27RA-DdzD-4Le.js → diagram-VX7I27RA-tn2xM1xu.js} +1 -1
  112. ksadk/server/static/assets/{diagram-Z3DM3KII-Du-nAJ9F.js → diagram-Z3DM3KII-BZPGBkw5.js} +1 -1
  113. ksadk/server/static/assets/{dist-ClxGviKw.js → dist-4zN1_tq5.js} +1 -1
  114. ksadk/server/static/assets/{dist-BE7bu-DL.js → dist-8VWI-2bZ.js} +1 -1
  115. ksadk/server/static/assets/{dist-BX8z72IC.js → dist-B-46q3Hk.js} +1 -1
  116. ksadk/server/static/assets/{dist-BjU6y-A2.js → dist-B0gdk4rl.js} +1 -1
  117. ksadk/server/static/assets/{dist-C_wsv-Qd.js → dist-B1oWRmrH.js} +1 -1
  118. ksadk/server/static/assets/{dist-ngtN0DJB.js → dist-BI1qQH4n.js} +1 -1
  119. ksadk/server/static/assets/{dist-dydu68Fl.js → dist-BJLUwH6W.js} +1 -1
  120. ksadk/server/static/assets/{dist-Dq9gLD7L.js → dist-Bbwqa8TG.js} +1 -1
  121. ksadk/server/static/assets/{dist-CttYUqzS.js → dist-Btyo4vX4.js} +1 -1
  122. ksadk/server/static/assets/{dist-CXYYBw3_.js → dist-C71CsujO.js} +1 -1
  123. ksadk/server/static/assets/{dist-dDdADKFA.js → dist-CXpH_Rdd.js} +1 -1
  124. ksadk/server/static/assets/{dist-CSh_DE14.js → dist-Cq4OL6nO.js} +1 -1
  125. ksadk/server/static/assets/{dist-8hqcx0sU.js → dist-D1V3f1B4.js} +1 -1
  126. ksadk/server/static/assets/{dist-BVDffZ0U.js → dist-DJmCPRVB.js} +1 -1
  127. ksadk/server/static/assets/{dist-DnfXs8Vn.js → dist-DQAB0qn_.js} +1 -1
  128. ksadk/server/static/assets/{dist-DNp6rLRA.js → dist-DUwKa_l6.js} +1 -1
  129. ksadk/server/static/assets/{dist-B7seoj3d.js → dist-DdRBIceA.js} +1 -1
  130. ksadk/server/static/assets/{dist-BytlxIDT.js → dist-DfGFrb0v.js} +1 -1
  131. ksadk/server/static/assets/{dist-Bf2M8m3N.js → dist-DjhwGUgZ.js} +1 -1
  132. ksadk/server/static/assets/{dist-W-TIVntx.js → dist-DyqV4fL4.js} +1 -1
  133. ksadk/server/static/assets/{dist-DUX-id_F.js → dist-M67Hwu0n.js} +1 -1
  134. ksadk/server/static/assets/{dist-DmldrHd_.js → dist-u8tVH5Ak.js} +1 -1
  135. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Da9C9NO1.js → ebnfDiagram-PWID7BFC-DVfMsLge.js} +1 -1
  136. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-EAGqqR79.js → erDiagram-SSCWMZ5O-CWEZSYaw.js} +1 -1
  137. ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +1 -0
  138. ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +1 -0
  139. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DqJsKb59.js → ganttDiagram-EL5Y4UJY-TWIxoyYL.js} +1 -1
  140. ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +1 -0
  141. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-B6g4dtDi.js → gitGraphDiagram-WWUBYQGX-DDh2hd2S.js} +1 -1
  142. ksadk/server/static/assets/index-B2k_urY8.js +241 -0
  143. ksadk/server/static/assets/index-ILPt6IWF.css +2 -0
  144. ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +1 -0
  145. ksadk/server/static/assets/{infoDiagram-RXCK75RN-Djm_nbd5.js → infoDiagram-RXCK75RN-CgoyWiDR.js} +1 -1
  146. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-DWya9SG2.js → ishikawaDiagram-5VMMS53U-CyRIu_om.js} +1 -1
  147. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DutxhSNI.js → journeyDiagram-EYS64GPL-DN5JXHzN.js} +1 -1
  148. ksadk/server/static/assets/{kanban-definition-3QL26DDD-DJdOF8Fm.js → kanban-definition-3QL26DDD-CNP3ui66.js} +1 -1
  149. ksadk/server/static/assets/{katex-vFWytM5c.js → katex-DWEzQy1d.js} +1 -1
  150. ksadk/server/static/assets/{linear-BHjG8b-J.js → linear-C-qHp7d2.js} +1 -1
  151. ksadk/server/static/assets/{mermaid-parser.core-KGSy4jWT.js → mermaid-parser.core-Cl-K943T.js} +2 -2
  152. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-9-HC88D4.js → mindmap-definition-FBJOCRG2-D5DB5mYm.js} +1 -1
  153. ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +1 -0
  154. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-DrEZd4fD.js → pegDiagram-XKGWAZYB-BQVc9ia_.js} +1 -1
  155. ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +1 -0
  156. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-DpjqOFFp.js → pieDiagram-E7YTZNPT-B6UCAvtY.js} +1 -1
  157. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BiNhgOXX.js → quadrantDiagram-AXDQQJYC-mIr2d3eb.js} +1 -1
  158. ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +1 -0
  159. ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +1 -0
  160. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +1 -0
  161. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +1 -0
  162. ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +1 -0
  163. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-_Y3Ojg6G.js → railroadDiagram-O6MQD6OU-Dt3FFDmK.js} +1 -1
  164. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-DeCFdg9K.js → requirementDiagram-EFPCY7ZU-Cz_vQtgF.js} +1 -1
  165. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-CPH75rhw.js → sankeyDiagram-P5KCCOFB-wlO1TsH5.js} +1 -1
  166. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-OEpQQdr4.js → sequenceDiagram-WJ2MYXX4-CHRbElYq.js} +1 -1
  167. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-heUErzhI.js → sizeCapture-X5ZJPWSS-DXX54iyO.js} +1 -1
  168. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DvA3jSMB.js → stateDiagram-HBIQ2CUA-Dp_lw9II.js} +1 -1
  169. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +1 -0
  170. ksadk/server/static/assets/{swimlanes-XN3QIQJK-CR-dfN_t.js → swimlanes-XN3QIQJK-D8O5UlLG.js} +1 -1
  171. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +8 -0
  172. ksadk/server/static/assets/{timeline-definition-24CTP7MA-DAVJf1TX.js → timeline-definition-24CTP7MA-8mfKcxvG.js} +1 -1
  173. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +1 -0
  174. ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +1 -0
  175. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-DwM8eDkh.js → vennDiagram-4TSXK5OY-EnNl0DE7.js} +1 -1
  176. ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +1 -0
  177. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DZL-Zz2t.js → wardleyDiagram-VM6X3IG4-DBu5fbYr.js} +1 -1
  178. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js → xychartDiagram-S5SC5T6Z-BSVXs4IY.js} +1 -1
  179. ksadk/server/static/index.html +2 -2
  180. ksadk/skills/service_client.py +48 -0
  181. ksadk/studio/agent_lifecycle.py +26 -20
  182. ksadk/studio/api.py +513 -71
  183. ksadk/studio/api_catalog_routes.py +5 -0
  184. ksadk/studio/api_contracts.py +34 -1
  185. ksadk/studio/api_plugin_routes.py +480 -0
  186. ksadk/studio/attachment_store.py +187 -0
  187. ksadk/studio/authoring.py +10 -4
  188. ksadk/studio/authoring_coordinator.py +12 -2
  189. ksadk/studio/builder.py +123 -43
  190. ksadk/studio/cloud.py +4 -0
  191. ksadk/studio/codex_agent_service.py +12 -1
  192. ksadk/studio/codex_builder.py +54 -15
  193. ksadk/studio/codex_manifest.py +21 -1
  194. ksadk/studio/codex_run.py +16 -4
  195. ksadk/studio/compatibility_report.py +445 -0
  196. ksadk/studio/compiler.py +6 -1
  197. ksadk/studio/contracts.py +123 -4
  198. ksadk/studio/dsh_provider_registration.py +768 -0
  199. ksadk/studio/event_store.py +54 -6
  200. ksadk/studio/framework_run.py +37 -4
  201. ksadk/studio/hosted_kernel.py +1 -1
  202. ksadk/studio/operations.py +12 -2
  203. ksadk/studio/plugin_composition.py +301 -0
  204. ksadk/studio/plugin_kernel_adapter.py +128 -0
  205. ksadk/studio/plugin_runtime.py +652 -0
  206. ksadk/studio/resource_catalog.py +6 -1
  207. ksadk/studio/run_service.py +713 -75
  208. ksadk/studio/runtime_source.py +9 -1
  209. ksadk/studio/scheduler_runtime.py +374 -0
  210. ksadk/studio/scheduler_service.py +211 -0
  211. ksadk/studio/service.py +672 -82
  212. ksadk/studio/shared_web.py +167 -28
  213. ksadk/studio/soul.py +52 -0
  214. ksadk/studio/static/assets/index-DXs1Eq4M.css +1 -0
  215. ksadk/studio/static/assets/index-DeDqwTsD.js +283 -0
  216. ksadk/studio/static/index.html +2 -2
  217. ksadk/studio/validator.py +1 -1
  218. ksadk/studio/workspace.py +1 -0
  219. ksadk/version.py +1 -1
  220. ksadk_runtime_common/workspace_files/path_utils.py +41 -0
  221. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +0 -1
  222. ksadk/server/static/assets/channel-4cQHKtx1.js +0 -1
  223. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +0 -1
  224. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +0 -1
  225. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +0 -1
  226. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +0 -1
  227. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +0 -1
  228. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +0 -1
  229. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +0 -1
  230. ksadk/server/static/assets/index-8ipRcQ-M.js +0 -240
  231. ksadk/server/static/assets/index-ByFCqjlh.css +0 -2
  232. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +0 -1
  233. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +0 -1
  234. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +0 -1
  235. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +0 -1
  236. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +0 -1
  237. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +0 -1
  238. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +0 -1
  239. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +0 -1
  240. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +0 -1
  241. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +0 -8
  242. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +0 -1
  243. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +0 -1
  244. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +0 -1
  245. ksadk/studio/static/assets/index-BLpcdrgW.css +0 -1
  246. ksadk/studio/static/assets/index-CYekR2Xv.js +0 -260
  247. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/WHEEL +0 -0
  248. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/entry_points.txt +0 -0
  249. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/licenses/LICENSE +0 -0
  250. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,563 @@
1
+ """Durable local persistence for Scheduler Lite.
2
+
3
+ This store is deliberately independent from AgentKernel's Inbox tables. It
4
+ owns scheduling decisions, occurrence identity and its *single process*
5
+ lease; AgentControl remains the only execution ingress.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import json
12
+ import sqlite3
13
+ from datetime import datetime, timezone
14
+ from pathlib import Path
15
+ from typing import Literal
16
+
17
+ from ksadk.scheduler.contracts import (
18
+ ScheduledTask,
19
+ ScheduleOccurrence,
20
+ ScheduleOccurrenceTransition,
21
+ )
22
+
23
+ _SCHEMA_VERSION = 2
24
+ _ACTIVE_STATES = ("claimed", "accepted", "running")
25
+ _SCHEMA = """
26
+ CREATE TABLE IF NOT EXISTS scheduler_tasks (
27
+ task_id TEXT PRIMARY KEY,
28
+ generation INTEGER NOT NULL,
29
+ body_json TEXT NOT NULL,
30
+ enabled INTEGER NOT NULL,
31
+ next_run_at TEXT,
32
+ created_at TEXT NOT NULL,
33
+ updated_at TEXT NOT NULL
34
+ );
35
+ CREATE INDEX IF NOT EXISTS idx_scheduler_tasks_due
36
+ ON scheduler_tasks (enabled, next_run_at);
37
+ CREATE TABLE IF NOT EXISTS scheduler_occurrences (
38
+ occurrence_id TEXT PRIMARY KEY,
39
+ task_id TEXT NOT NULL,
40
+ generation INTEGER NOT NULL,
41
+ scheduled_for TEXT NOT NULL,
42
+ trigger_kind TEXT NOT NULL,
43
+ body_json TEXT NOT NULL,
44
+ state TEXT NOT NULL,
45
+ command_id TEXT,
46
+ completed_at TEXT,
47
+ UNIQUE(task_id, generation, scheduled_for, trigger_kind)
48
+ );
49
+ CREATE INDEX IF NOT EXISTS idx_scheduler_occurrences_task_state
50
+ ON scheduler_occurrences (task_id, state, scheduled_for DESC);
51
+ CREATE TABLE IF NOT EXISTS scheduler_leases (
52
+ lease_name TEXT PRIMARY KEY,
53
+ owner_id TEXT NOT NULL,
54
+ expires_at TEXT NOT NULL
55
+ );
56
+ """
57
+
58
+
59
+ def _iso(value: datetime) -> str:
60
+ if value.tzinfo is None:
61
+ raise ValueError("timestamp must include a timezone")
62
+ return value.astimezone(timezone.utc).isoformat().replace("+00:00", "Z")
63
+
64
+
65
+ def _parse(value: str) -> datetime:
66
+ return datetime.fromisoformat(value.replace("Z", "+00:00")).astimezone(timezone.utc)
67
+
68
+
69
+ def occurrence_id(
70
+ task_id: str,
71
+ generation: int,
72
+ scheduled_for: datetime,
73
+ trigger: Literal["schedule", "manual"] = "schedule",
74
+ ) -> str:
75
+ raw = f"{task_id}\x00{generation}\x00{_iso(scheduled_for)}\x00{trigger}".encode()
76
+ return f"occ_{hashlib.sha256(raw).hexdigest()[:32]}"
77
+
78
+
79
+ def _session_id(task: ScheduledTask, *, occurrence_id_value: str) -> str:
80
+ if task.continuity == "continue_session":
81
+ assert task.target.session_id is not None
82
+ return task.target.session_id
83
+ # A new scheduled start has an independent durable Session namespace. It
84
+ # is derived from the immutable occurrence id so a retry cannot create a
85
+ # second conversation.
86
+ return f"sched-{occurrence_id_value}"
87
+
88
+
89
+ class SchedulerSQLiteStore:
90
+ """Synchronous SQLite store; callers may use it through ``to_thread``.
91
+
92
+ Every mutation uses its own connection and ``BEGIN IMMEDIATE``. That is
93
+ intentional: this component has no undeclared aiosqlite dependency and
94
+ remains correct when multiple local Studio processes contend for its DB.
95
+ """
96
+
97
+ def __init__(self, path: str | Path) -> None:
98
+ self.path = Path(path).expanduser().resolve()
99
+ self.path.parent.mkdir(parents=True, exist_ok=True)
100
+ self.ensure_schema()
101
+
102
+ def _connect(self) -> sqlite3.Connection:
103
+ connection = sqlite3.connect(self.path, timeout=5, isolation_level=None)
104
+ connection.row_factory = sqlite3.Row
105
+ connection.execute("PRAGMA journal_mode=WAL")
106
+ connection.execute("PRAGMA synchronous=FULL")
107
+ return connection
108
+
109
+ def ensure_schema(self) -> None:
110
+ with self._connect() as connection:
111
+ connection.executescript(_SCHEMA)
112
+ connection.execute(f"PRAGMA user_version={_SCHEMA_VERSION}")
113
+
114
+ def put_task(self, task: ScheduledTask, *, generation: int | None = None) -> int:
115
+ now = _iso(datetime.now(timezone.utc))
116
+ encoded = task.model_dump_json(by_alias=True, exclude_none=True)
117
+ with self._connect() as connection:
118
+ connection.execute("BEGIN IMMEDIATE")
119
+ existing = connection.execute(
120
+ "SELECT generation, created_at FROM scheduler_tasks WHERE task_id=?",
121
+ (task.task_id,),
122
+ ).fetchone()
123
+ actual_generation = generation
124
+ if actual_generation is None:
125
+ actual_generation = int(existing["generation"]) + 1 if existing else 1
126
+ created_at = existing["created_at"] if existing else _iso(task.created_at)
127
+ connection.execute(
128
+ """INSERT INTO scheduler_tasks(
129
+ task_id,generation,body_json,enabled,next_run_at,created_at,updated_at
130
+ )
131
+ VALUES(?,?,?,?,?,?,?)
132
+ ON CONFLICT(task_id) DO UPDATE SET generation=excluded.generation,
133
+ body_json=excluded.body_json,enabled=excluded.enabled,next_run_at=excluded.next_run_at,
134
+ updated_at=excluded.updated_at""",
135
+ (
136
+ task.task_id,
137
+ actual_generation,
138
+ encoded,
139
+ int(task.enabled),
140
+ _iso(task.next_run_at) if task.next_run_at else None,
141
+ created_at,
142
+ now,
143
+ ),
144
+ )
145
+ connection.commit()
146
+ return actual_generation
147
+
148
+ def get_task(self, task_id: str) -> tuple[ScheduledTask, int] | None:
149
+ with self._connect() as connection:
150
+ row = connection.execute(
151
+ "SELECT body_json,generation,next_run_at,enabled "
152
+ "FROM scheduler_tasks WHERE task_id=?",
153
+ (task_id,),
154
+ ).fetchone()
155
+ if row is None:
156
+ return None
157
+ body = json.loads(row["body_json"])
158
+ body["nextRunAt"] = row["next_run_at"]
159
+ body["enabled"] = bool(row["enabled"])
160
+ return ScheduledTask.model_validate(body), int(row["generation"])
161
+
162
+ def list_due(self, now: datetime) -> list[tuple[ScheduledTask, int]]:
163
+ with self._connect() as connection:
164
+ rows = connection.execute(
165
+ """SELECT body_json,generation,next_run_at FROM scheduler_tasks
166
+ WHERE enabled=1 AND next_run_at IS NOT NULL AND next_run_at<=?
167
+ ORDER BY next_run_at,task_id""",
168
+ (_iso(now),),
169
+ ).fetchall()
170
+ result: list[tuple[ScheduledTask, int]] = []
171
+ for row in rows:
172
+ body = json.loads(row["body_json"])
173
+ body["nextRunAt"] = row["next_run_at"]
174
+ result.append((ScheduledTask.model_validate(body), int(row["generation"])))
175
+ return result
176
+
177
+ def list_tasks(self) -> list[tuple[ScheduledTask, int]]:
178
+ with self._connect() as connection:
179
+ rows = connection.execute(
180
+ "SELECT body_json,generation,next_run_at,enabled FROM scheduler_tasks "
181
+ "ORDER BY updated_at DESC,task_id"
182
+ ).fetchall()
183
+ result: list[tuple[ScheduledTask, int]] = []
184
+ for row in rows:
185
+ body = json.loads(row["body_json"])
186
+ body["nextRunAt"] = row["next_run_at"]
187
+ body["enabled"] = bool(row["enabled"])
188
+ result.append((ScheduledTask.model_validate(body), int(row["generation"])))
189
+ return result
190
+
191
+ def delete_task(self, task_id: str) -> bool:
192
+ """Remove the scheduling intent but retain immutable occurrence history."""
193
+
194
+ with self._connect() as connection:
195
+ connection.execute("BEGIN IMMEDIATE")
196
+ removed = connection.execute(
197
+ "DELETE FROM scheduler_tasks WHERE task_id=?", (task_id,)
198
+ ).rowcount
199
+ connection.commit()
200
+ return removed == 1
201
+
202
+ def list_occurrences(self, task_id: str, *, limit: int = 50) -> list[ScheduleOccurrence]:
203
+ if limit < 1 or limit > 200:
204
+ raise ValueError("occurrence limit must be between 1 and 200")
205
+ with self._connect() as connection:
206
+ rows = connection.execute(
207
+ """SELECT body_json FROM scheduler_occurrences WHERE task_id=?
208
+ ORDER BY scheduled_for DESC,occurrence_id DESC LIMIT ?""",
209
+ (task_id, limit),
210
+ ).fetchall()
211
+ return [ScheduleOccurrence.model_validate_json(row["body_json"]) for row in rows]
212
+
213
+ def list_all_occurrences(self, *, limit: int = 200) -> list[ScheduleOccurrence]:
214
+ """Return cross-task history, including records whose task was deleted."""
215
+
216
+ if limit < 1 or limit > 500:
217
+ raise ValueError("occurrence limit must be between 1 and 500")
218
+ with self._connect() as connection:
219
+ rows = connection.execute(
220
+ "SELECT body_json FROM scheduler_occurrences "
221
+ "ORDER BY scheduled_for DESC,occurrence_id DESC LIMIT ?",
222
+ (limit,),
223
+ ).fetchall()
224
+ return [ScheduleOccurrence.model_validate_json(row["body_json"]) for row in rows]
225
+
226
+ def list_active_occurrences(self, *, limit: int = 200) -> list[ScheduleOccurrence]:
227
+ """Return only non-terminal occurrences for event reconciliation.
228
+
229
+ The target snapshot is stored on the occurrence itself, so deleting a
230
+ task deliberately does not orphan a previously accepted execution.
231
+ """
232
+
233
+ if limit < 1 or limit > 200:
234
+ raise ValueError("active occurrence limit must be between 1 and 200")
235
+ placeholders = ",".join("?" for _ in _ACTIVE_STATES)
236
+ with self._connect() as connection:
237
+ rows = connection.execute(
238
+ "SELECT body_json FROM scheduler_occurrences "
239
+ f"WHERE state IN ({placeholders}) "
240
+ "ORDER BY scheduled_for,occurrence_id LIMIT ?",
241
+ (*_ACTIVE_STATES, limit),
242
+ ).fetchall()
243
+ return [ScheduleOccurrence.model_validate_json(row["body_json"]) for row in rows]
244
+
245
+ def has_active_occurrence(self, task_id: str) -> bool:
246
+ placeholders = ",".join("?" for _ in _ACTIVE_STATES)
247
+ with self._connect() as connection:
248
+ row = connection.execute(
249
+ "SELECT 1 FROM scheduler_occurrences "
250
+ f"WHERE task_id=? AND state IN ({placeholders}) LIMIT 1",
251
+ (task_id, *_ACTIVE_STATES),
252
+ ).fetchone()
253
+ return row is not None
254
+
255
+ def claim_and_advance(
256
+ self,
257
+ task: ScheduledTask,
258
+ *,
259
+ generation: int,
260
+ next_run_at: datetime | None,
261
+ state: Literal["claimed", "skipped"] = "claimed",
262
+ detail: str | None = None,
263
+ trigger: Literal["schedule", "manual"] = "schedule",
264
+ claimed_at: datetime | None = None,
265
+ ) -> ScheduleOccurrence | None:
266
+ if task.next_run_at is None:
267
+ raise ValueError("task must have next_run_at before it can be claimed")
268
+ scheduled_for = task.next_run_at
269
+ now = claimed_at or datetime.now(timezone.utc)
270
+ completed_at = now if state == "skipped" else None
271
+ transitions = [ScheduleOccurrenceTransition(state="claimed", at=now)]
272
+ if state == "skipped":
273
+ transitions.append(ScheduleOccurrenceTransition(state="skipped", at=now, detail=detail))
274
+ occurrence = ScheduleOccurrence(
275
+ occurrence_id=occurrence_id(task.task_id, generation, scheduled_for, trigger),
276
+ task_id=task.task_id,
277
+ target=task.target,
278
+ scheduled_for=scheduled_for,
279
+ session_id=_session_id(
280
+ task,
281
+ occurrence_id_value=occurrence_id(task.task_id, generation, scheduled_for, trigger),
282
+ ),
283
+ trigger=trigger,
284
+ state=state,
285
+ claimed_at=now,
286
+ detail=detail,
287
+ completed_at=completed_at,
288
+ transitions=tuple(transitions),
289
+ )
290
+ with self._connect() as connection:
291
+ connection.execute("BEGIN IMMEDIATE")
292
+ updated = connection.execute(
293
+ """UPDATE scheduler_tasks SET next_run_at=?,updated_at=?
294
+ WHERE task_id=? AND generation=? AND next_run_at=? AND enabled=1""",
295
+ (
296
+ _iso(next_run_at) if next_run_at else None,
297
+ _iso(now),
298
+ task.task_id,
299
+ generation,
300
+ _iso(scheduled_for),
301
+ ),
302
+ ).rowcount
303
+ if updated != 1:
304
+ connection.rollback()
305
+ return None
306
+ connection.execute(
307
+ """INSERT OR IGNORE INTO scheduler_occurrences(
308
+ occurrence_id,task_id,generation,scheduled_for,trigger_kind,body_json,state,command_id,completed_at)
309
+ VALUES(?,?,?,?,?,?,?,?,?)""",
310
+ (
311
+ occurrence.occurrence_id,
312
+ task.task_id,
313
+ generation,
314
+ _iso(scheduled_for),
315
+ trigger,
316
+ occurrence.model_dump_json(by_alias=True, exclude_none=True),
317
+ state,
318
+ None,
319
+ _iso(completed_at) if completed_at else None,
320
+ ),
321
+ )
322
+ connection.commit()
323
+ return occurrence
324
+
325
+ def mark_accepted(
326
+ self,
327
+ occurrence_id_value: str,
328
+ command_id: str,
329
+ *,
330
+ accepted_seq: int | None = None,
331
+ ) -> ScheduleOccurrence:
332
+ return self._transition(
333
+ occurrence_id_value,
334
+ state="accepted",
335
+ command_id=command_id,
336
+ accepted_seq=accepted_seq,
337
+ last_event_seq=accepted_seq,
338
+ accepted_at=datetime.now(timezone.utc),
339
+ )
340
+
341
+ def claim_manual(
342
+ self,
343
+ task: ScheduledTask,
344
+ *,
345
+ generation: int,
346
+ now: datetime,
347
+ ) -> ScheduleOccurrence | None:
348
+ """Create a durable manual occurrence without changing the timetable."""
349
+
350
+ occurrence = ScheduleOccurrence(
351
+ occurrence_id=occurrence_id(task.task_id, generation, now, "manual"),
352
+ task_id=task.task_id,
353
+ target=task.target,
354
+ scheduled_for=now,
355
+ session_id=_session_id(
356
+ task,
357
+ occurrence_id_value=occurrence_id(task.task_id, generation, now, "manual"),
358
+ ),
359
+ trigger="manual",
360
+ state="claimed",
361
+ claimed_at=now,
362
+ transitions=(ScheduleOccurrenceTransition(state="claimed", at=now),),
363
+ )
364
+ with self._connect() as connection:
365
+ connection.execute("BEGIN IMMEDIATE")
366
+ current = connection.execute(
367
+ "SELECT generation,enabled FROM scheduler_tasks WHERE task_id=?",
368
+ (task.task_id,),
369
+ ).fetchone()
370
+ if (
371
+ current is None
372
+ or int(current["generation"]) != generation
373
+ or not current["enabled"]
374
+ ):
375
+ connection.rollback()
376
+ return None
377
+ inserted = connection.execute(
378
+ """INSERT OR IGNORE INTO scheduler_occurrences(
379
+ occurrence_id,task_id,generation,scheduled_for,trigger_kind,
380
+ body_json,state,command_id,completed_at
381
+ ) VALUES(?,?,?,?,?,?,?,?,?)""",
382
+ (
383
+ occurrence.occurrence_id,
384
+ task.task_id,
385
+ generation,
386
+ _iso(now),
387
+ "manual",
388
+ occurrence.model_dump_json(by_alias=True, exclude_none=True),
389
+ occurrence.state,
390
+ None,
391
+ None,
392
+ ),
393
+ ).rowcount
394
+ if inserted != 1:
395
+ connection.rollback()
396
+ return None
397
+ connection.commit()
398
+ return occurrence
399
+
400
+ def finish(
401
+ self,
402
+ occurrence_id_value: str,
403
+ *,
404
+ succeeded: bool,
405
+ error_code: str | None = None,
406
+ detail: str | None = None,
407
+ ) -> ScheduleOccurrence:
408
+ if not succeeded and not error_code:
409
+ raise ValueError("failed scheduler occurrence requires error_code")
410
+ return self._transition(
411
+ occurrence_id_value,
412
+ state="succeeded" if succeeded else "failed",
413
+ error_code=error_code,
414
+ detail=detail,
415
+ completed_at=datetime.now(timezone.utc),
416
+ )
417
+
418
+ def mark_running(
419
+ self,
420
+ occurrence_id_value: str,
421
+ *,
422
+ run_id: str,
423
+ last_event_seq: int,
424
+ ) -> ScheduleOccurrence:
425
+ return self._transition(
426
+ occurrence_id_value,
427
+ state="running",
428
+ run_id=run_id,
429
+ started_at=datetime.now(timezone.utc),
430
+ last_event_seq=last_event_seq,
431
+ )
432
+
433
+ def bind_run(
434
+ self,
435
+ occurrence_id_value: str,
436
+ *,
437
+ run_id: str,
438
+ last_event_seq: int,
439
+ ) -> ScheduleOccurrence:
440
+ """Record a durable run identity before that run becomes runnable."""
441
+
442
+ return self._transition(
443
+ occurrence_id_value,
444
+ run_id=run_id,
445
+ last_event_seq=last_event_seq,
446
+ )
447
+
448
+ def advance_reconciliation_cursor(
449
+ self, occurrence_id_value: str, *, last_event_seq: int
450
+ ) -> ScheduleOccurrence:
451
+ return self._transition(
452
+ occurrence_id_value,
453
+ last_event_seq=last_event_seq,
454
+ )
455
+
456
+ def _transition(self, occurrence_id_value: str, **updates: object) -> ScheduleOccurrence:
457
+ with self._connect() as connection:
458
+ connection.execute("BEGIN IMMEDIATE")
459
+ row = connection.execute(
460
+ "SELECT body_json,state FROM scheduler_occurrences WHERE occurrence_id=?",
461
+ (occurrence_id_value,),
462
+ ).fetchone()
463
+ if row is None:
464
+ connection.rollback()
465
+ raise KeyError(occurrence_id_value)
466
+ body = json.loads(row["body_json"])
467
+ current = ScheduleOccurrence.model_validate(body)
468
+ terminal = {"succeeded", "failed", "skipped", "cancelled"}
469
+ # Terminal facts are first-wins. A replayed SSE frame or a later
470
+ # contradictory event must never rewrite auditable scheduler
471
+ # history after it has reached a conclusion.
472
+ if current.state in terminal:
473
+ connection.rollback()
474
+ return current
475
+ current_seq = current.last_event_seq
476
+ requested_seq = updates.get("last_event_seq")
477
+ if (
478
+ isinstance(requested_seq, int)
479
+ and current_seq is not None
480
+ and requested_seq < current_seq
481
+ ):
482
+ connection.rollback()
483
+ return current
484
+ # Stored JSON uses the public camelCase aliases. Updating with a
485
+ # Python field name while an older alias is present would create
486
+ # two values for one field and Pydantic correctly rejects it as an
487
+ # ambiguous/extra input. Normalize every mutation at this one
488
+ # persistence boundary instead.
489
+ for key, value in updates.items():
490
+ if value is None:
491
+ continue
492
+ field = ScheduleOccurrence.model_fields.get(key)
493
+ encoded_key = field.alias if field and field.alias else key
494
+ body[encoded_key] = _iso(value) if isinstance(value, datetime) else value
495
+ requested_state = updates.get("state")
496
+ if isinstance(requested_state, str) and requested_state != current.state:
497
+ transition_at = next(
498
+ (
499
+ value
500
+ for name in ("completed_at", "started_at", "accepted_at")
501
+ if isinstance((value := updates.get(name)), datetime)
502
+ ),
503
+ datetime.now(timezone.utc),
504
+ )
505
+ transitions = list(current.transitions)
506
+ if transitions and transition_at < transitions[-1].at:
507
+ # Custom/test clocks and small host clock corrections must
508
+ # not make a durable audit timeline go backwards.
509
+ transition_at = transitions[-1].at
510
+ transitions.append(
511
+ ScheduleOccurrenceTransition(
512
+ state=requested_state, # type: ignore[arg-type]
513
+ at=transition_at,
514
+ detail=(str(updates["detail"]) if updates.get("detail") else None),
515
+ error_code=(
516
+ str(updates["error_code"]) if updates.get("error_code") else None
517
+ ),
518
+ )
519
+ )
520
+ body["transitions"] = [
521
+ item.model_dump(mode="json", by_alias=True, exclude_none=True)
522
+ for item in transitions
523
+ ]
524
+ occurrence = ScheduleOccurrence.model_validate(body)
525
+ connection.execute(
526
+ """UPDATE scheduler_occurrences SET body_json=?,state=?,command_id=?,completed_at=?
527
+ WHERE occurrence_id=?""",
528
+ (
529
+ occurrence.model_dump_json(by_alias=True, exclude_none=True),
530
+ occurrence.state,
531
+ occurrence.command_id,
532
+ _iso(occurrence.completed_at) if occurrence.completed_at else None,
533
+ occurrence_id_value,
534
+ ),
535
+ )
536
+ connection.commit()
537
+ return occurrence
538
+
539
+ def acquire_lease(self, *, owner_id: str, now: datetime, ttl_seconds: int = 30) -> bool:
540
+ expiry = now.astimezone(timezone.utc).timestamp() + ttl_seconds
541
+ expires_at = datetime.fromtimestamp(expiry, tz=timezone.utc)
542
+ with self._connect() as connection:
543
+ connection.execute("BEGIN IMMEDIATE")
544
+ row = connection.execute(
545
+ "SELECT owner_id,expires_at FROM scheduler_leases "
546
+ "WHERE lease_name='local-scheduler'"
547
+ ).fetchone()
548
+ allowed = row is None or _parse(row["expires_at"]) <= now or row["owner_id"] == owner_id
549
+ if allowed:
550
+ connection.execute(
551
+ """INSERT INTO scheduler_leases(lease_name,owner_id,expires_at)
552
+ VALUES('local-scheduler',?,?)
553
+ ON CONFLICT(lease_name) DO UPDATE SET
554
+ owner_id=excluded.owner_id,expires_at=excluded.expires_at""",
555
+ (owner_id, _iso(expires_at)),
556
+ )
557
+ connection.commit()
558
+ return True
559
+ connection.rollback()
560
+ return False
561
+
562
+
563
+ __all__ = ["SchedulerSQLiteStore", "occurrence_id"]
@@ -1 +1 @@
1
- import{St as e,Tt as t,bt as n,gt as r,lt as i,n as a,t as o,ut as s,xt as c}from"./index-8ipRcQ-M.js";var l=t(e(),1),u=n();function d(){let e=c(e=>e.visible),t=c(e=>e.content),n=c(e=>e.type),d=c(e=>e.hide),f=(0,l.useRef)(null);if(a(f),!e||!t)return null;let p=o(t);return(0,u.jsxs)(`aside`,{className:i(`flex h-full flex-shrink-0 flex-col border-l border-slate-200/30 bg-white dark:border-slate-800/40 dark:bg-slate-950`,`w-[min(42rem,50vw)]`),children:[(0,u.jsxs)(`div`,{className:`flex h-14 flex-shrink-0 items-center justify-between border-b border-slate-200/30 px-4 dark:border-slate-800/40`,children:[(0,u.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,u.jsx)(`span`,{className:`text-sm font-semibold text-slate-900 dark:text-slate-100`,children:`Artifact`}),(0,u.jsx)(`span`,{className:`rounded-md bg-slate-100 px-1.5 py-0.5 font-mono text-[11px] text-slate-500 dark:bg-slate-900 dark:text-slate-400`,children:n})]}),(0,u.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,u.jsxs)(`button`,{type:`button`,onClick:()=>{let e=new Blob([t],{type:`text/html;charset=utf-8`}),r=URL.createObjectURL(e),i=document.createElement(`a`);i.href=r,i.download=`artifact.${n===`svg`?`svg`:`html`}`,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)},className:`inline-flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-xs font-medium text-slate-600 transition hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-900`,title:`Download`,children:[(0,u.jsx)(r,{className:`h-3.5 w-3.5`}),`Download`]}),(0,u.jsx)(`button`,{type:`button`,onClick:d,className:`rounded-lg p-1.5 text-slate-500 transition hover:bg-slate-100 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-slate-900 dark:hover:text-slate-100`,"aria-label":`Close Artifact`,title:`Close`,children:(0,u.jsx)(s,{className:`h-4 w-4`})})]})]}),(0,u.jsx)(`div`,{className:`min-h-0 flex-1`,children:(0,u.jsx)(`iframe`,{ref:f,srcDoc:p,sandbox:`allow-scripts allow-downloads`,title:`Artifact Preview`,className:`h-full w-full border-0 bg-white`})})]})}export{d as ArtifactsPanel};
1
+ import{St as e,Tt as t,bt as n,gt as r,lt as i,n as a,t as o,ut as s,xt as c}from"./index-B2k_urY8.js";var l=t(e(),1),u=n();function d(){let e=c(e=>e.visible),t=c(e=>e.content),n=c(e=>e.type),d=c(e=>e.hide),f=(0,l.useRef)(null);if(a(f),!e||!t)return null;let p=o(t);return(0,u.jsxs)(`aside`,{className:i(`flex h-full flex-shrink-0 flex-col border-l border-slate-200/30 bg-white dark:border-slate-800/40 dark:bg-slate-950`,`w-[min(42rem,50vw)]`),children:[(0,u.jsxs)(`div`,{className:`flex h-14 flex-shrink-0 items-center justify-between border-b border-slate-200/30 px-4 dark:border-slate-800/40`,children:[(0,u.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,u.jsx)(`span`,{className:`text-sm font-semibold text-slate-900 dark:text-slate-100`,children:`Artifact`}),(0,u.jsx)(`span`,{className:`rounded-md bg-slate-100 px-1.5 py-0.5 font-mono text-[11px] text-slate-500 dark:bg-slate-900 dark:text-slate-400`,children:n})]}),(0,u.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,u.jsxs)(`button`,{type:`button`,onClick:()=>{let e=new Blob([t],{type:`text/html;charset=utf-8`}),r=URL.createObjectURL(e),i=document.createElement(`a`);i.href=r,i.download=`artifact.${n===`svg`?`svg`:`html`}`,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)},className:`inline-flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-xs font-medium text-slate-600 transition hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-900`,title:`Download`,children:[(0,u.jsx)(r,{className:`h-3.5 w-3.5`}),`Download`]}),(0,u.jsx)(`button`,{type:`button`,onClick:d,className:`rounded-lg p-1.5 text-slate-500 transition hover:bg-slate-100 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-slate-900 dark:hover:text-slate-100`,"aria-label":`Close Artifact`,title:`Close`,children:(0,u.jsx)(s,{className:`h-4 w-4`})})]})]}),(0,u.jsx)(`div`,{className:`min-h-0 flex-1`,children:(0,u.jsx)(`iframe`,{ref:f,srcDoc:p,sandbox:`allow-scripts allow-downloads`,title:`Artifact Preview`,className:`h-full w-full border-0 bg-white`})})]})}export{d as ArtifactsPanel};