aethergraph 0.1.0a1__py3-none-any.whl → 0.1.0a2__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 (267) hide show
  1. aethergraph/__init__.py +4 -10
  2. aethergraph/__main__.py +293 -0
  3. aethergraph/api/v1/__init__.py +0 -0
  4. aethergraph/api/v1/agents.py +46 -0
  5. aethergraph/api/v1/apps.py +70 -0
  6. aethergraph/api/v1/artifacts.py +415 -0
  7. aethergraph/api/v1/channels.py +89 -0
  8. aethergraph/api/v1/deps.py +168 -0
  9. aethergraph/api/v1/graphs.py +259 -0
  10. aethergraph/api/v1/identity.py +25 -0
  11. aethergraph/api/v1/memory.py +353 -0
  12. aethergraph/api/v1/misc.py +47 -0
  13. aethergraph/api/v1/pagination.py +29 -0
  14. aethergraph/api/v1/runs.py +568 -0
  15. aethergraph/api/v1/schemas.py +535 -0
  16. aethergraph/api/v1/session.py +323 -0
  17. aethergraph/api/v1/stats.py +201 -0
  18. aethergraph/api/v1/viz.py +152 -0
  19. aethergraph/config/config.py +22 -0
  20. aethergraph/config/loader.py +3 -2
  21. aethergraph/config/storage.py +209 -0
  22. aethergraph/contracts/__init__.py +0 -0
  23. aethergraph/contracts/services/__init__.py +0 -0
  24. aethergraph/contracts/services/artifacts.py +27 -14
  25. aethergraph/contracts/services/memory.py +45 -17
  26. aethergraph/contracts/services/metering.py +129 -0
  27. aethergraph/contracts/services/runs.py +50 -0
  28. aethergraph/contracts/services/sessions.py +87 -0
  29. aethergraph/contracts/services/state_stores.py +3 -0
  30. aethergraph/contracts/services/viz.py +44 -0
  31. aethergraph/contracts/storage/artifact_index.py +88 -0
  32. aethergraph/contracts/storage/artifact_store.py +99 -0
  33. aethergraph/contracts/storage/async_kv.py +34 -0
  34. aethergraph/contracts/storage/blob_store.py +50 -0
  35. aethergraph/contracts/storage/doc_store.py +35 -0
  36. aethergraph/contracts/storage/event_log.py +31 -0
  37. aethergraph/contracts/storage/vector_index.py +48 -0
  38. aethergraph/core/__init__.py +0 -0
  39. aethergraph/core/execution/forward_scheduler.py +13 -2
  40. aethergraph/core/execution/global_scheduler.py +21 -15
  41. aethergraph/core/execution/step_forward.py +10 -1
  42. aethergraph/core/graph/__init__.py +0 -0
  43. aethergraph/core/graph/graph_builder.py +8 -4
  44. aethergraph/core/graph/graph_fn.py +156 -15
  45. aethergraph/core/graph/graph_spec.py +8 -0
  46. aethergraph/core/graph/graphify.py +146 -27
  47. aethergraph/core/graph/node_spec.py +0 -2
  48. aethergraph/core/graph/node_state.py +3 -0
  49. aethergraph/core/graph/task_graph.py +39 -1
  50. aethergraph/core/runtime/__init__.py +0 -0
  51. aethergraph/core/runtime/ad_hoc_context.py +64 -4
  52. aethergraph/core/runtime/base_service.py +28 -4
  53. aethergraph/core/runtime/execution_context.py +13 -15
  54. aethergraph/core/runtime/graph_runner.py +222 -37
  55. aethergraph/core/runtime/node_context.py +510 -6
  56. aethergraph/core/runtime/node_services.py +12 -5
  57. aethergraph/core/runtime/recovery.py +15 -1
  58. aethergraph/core/runtime/run_manager.py +783 -0
  59. aethergraph/core/runtime/run_manager_local.py +204 -0
  60. aethergraph/core/runtime/run_registration.py +2 -2
  61. aethergraph/core/runtime/run_types.py +89 -0
  62. aethergraph/core/runtime/runtime_env.py +136 -7
  63. aethergraph/core/runtime/runtime_metering.py +71 -0
  64. aethergraph/core/runtime/runtime_registry.py +36 -13
  65. aethergraph/core/runtime/runtime_services.py +194 -6
  66. aethergraph/core/tools/builtins/toolset.py +1 -1
  67. aethergraph/core/tools/toolkit.py +5 -0
  68. aethergraph/plugins/agents/default_chat_agent copy.py +90 -0
  69. aethergraph/plugins/agents/default_chat_agent.py +171 -0
  70. aethergraph/plugins/agents/shared.py +81 -0
  71. aethergraph/plugins/channel/adapters/webui.py +112 -112
  72. aethergraph/plugins/channel/routes/webui_routes.py +367 -102
  73. aethergraph/plugins/channel/utils/slack_utils.py +115 -59
  74. aethergraph/plugins/channel/utils/telegram_utils.py +88 -47
  75. aethergraph/plugins/channel/websockets/weibui_ws.py +172 -0
  76. aethergraph/runtime/__init__.py +15 -0
  77. aethergraph/server/app_factory.py +190 -34
  78. aethergraph/server/clients/channel_client.py +202 -0
  79. aethergraph/server/http/channel_http_routes.py +116 -0
  80. aethergraph/server/http/channel_ws_routers.py +45 -0
  81. aethergraph/server/loading.py +117 -0
  82. aethergraph/server/server.py +131 -0
  83. aethergraph/server/server_state.py +240 -0
  84. aethergraph/server/start.py +227 -66
  85. aethergraph/server/ui_static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  86. aethergraph/server/ui_static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  87. aethergraph/server/ui_static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  88. aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  89. aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  90. aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  91. aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  92. aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  93. aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  94. aethergraph/server/ui_static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  95. aethergraph/server/ui_static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  96. aethergraph/server/ui_static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  97. aethergraph/server/ui_static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  98. aethergraph/server/ui_static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  99. aethergraph/server/ui_static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  100. aethergraph/server/ui_static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  101. aethergraph/server/ui_static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  102. aethergraph/server/ui_static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  103. aethergraph/server/ui_static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  104. aethergraph/server/ui_static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  105. aethergraph/server/ui_static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  106. aethergraph/server/ui_static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  107. aethergraph/server/ui_static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  108. aethergraph/server/ui_static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  109. aethergraph/server/ui_static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  110. aethergraph/server/ui_static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  111. aethergraph/server/ui_static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  112. aethergraph/server/ui_static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  113. aethergraph/server/ui_static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  114. aethergraph/server/ui_static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  115. aethergraph/server/ui_static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  116. aethergraph/server/ui_static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  117. aethergraph/server/ui_static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  118. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  119. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  120. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  121. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  122. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  123. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  124. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  125. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  126. aethergraph/server/ui_static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  127. aethergraph/server/ui_static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  128. aethergraph/server/ui_static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  129. aethergraph/server/ui_static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  130. aethergraph/server/ui_static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  131. aethergraph/server/ui_static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  132. aethergraph/server/ui_static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  133. aethergraph/server/ui_static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  134. aethergraph/server/ui_static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  135. aethergraph/server/ui_static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  136. aethergraph/server/ui_static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  137. aethergraph/server/ui_static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  138. aethergraph/server/ui_static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  139. aethergraph/server/ui_static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  140. aethergraph/server/ui_static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  141. aethergraph/server/ui_static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  142. aethergraph/server/ui_static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  143. aethergraph/server/ui_static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  144. aethergraph/server/ui_static/assets/index-BR5GtXcZ.css +1 -0
  145. aethergraph/server/ui_static/assets/index-CQ0HZZ83.js +400 -0
  146. aethergraph/server/ui_static/index.html +15 -0
  147. aethergraph/server/ui_static/logo.png +0 -0
  148. aethergraph/services/artifacts/__init__.py +0 -0
  149. aethergraph/services/artifacts/facade.py +1239 -132
  150. aethergraph/services/auth/{dev.py → authn.py} +0 -8
  151. aethergraph/services/auth/authz.py +100 -0
  152. aethergraph/services/channel/__init__.py +0 -0
  153. aethergraph/services/channel/channel_bus.py +19 -1
  154. aethergraph/services/channel/factory.py +13 -1
  155. aethergraph/services/channel/ingress.py +311 -0
  156. aethergraph/services/channel/queue_adapter.py +75 -0
  157. aethergraph/services/channel/session.py +502 -19
  158. aethergraph/services/container/default_container.py +122 -43
  159. aethergraph/services/continuations/continuation.py +6 -0
  160. aethergraph/services/continuations/stores/fs_store.py +19 -0
  161. aethergraph/services/eventhub/event_hub.py +76 -0
  162. aethergraph/services/kv/__init__.py +0 -0
  163. aethergraph/services/kv/ephemeral.py +244 -0
  164. aethergraph/services/llm/__init__.py +0 -0
  165. aethergraph/services/llm/generic_client copy.py +691 -0
  166. aethergraph/services/llm/generic_client.py +1288 -187
  167. aethergraph/services/llm/providers.py +3 -1
  168. aethergraph/services/llm/types.py +47 -0
  169. aethergraph/services/llm/utils.py +284 -0
  170. aethergraph/services/logger/std.py +3 -0
  171. aethergraph/services/mcp/__init__.py +9 -0
  172. aethergraph/services/mcp/http_client.py +38 -0
  173. aethergraph/services/mcp/service.py +225 -1
  174. aethergraph/services/mcp/stdio_client.py +41 -6
  175. aethergraph/services/mcp/ws_client.py +44 -2
  176. aethergraph/services/memory/__init__.py +0 -0
  177. aethergraph/services/memory/distillers/llm_long_term.py +234 -0
  178. aethergraph/services/memory/distillers/llm_meta_summary.py +398 -0
  179. aethergraph/services/memory/distillers/long_term.py +225 -0
  180. aethergraph/services/memory/facade/__init__.py +3 -0
  181. aethergraph/services/memory/facade/chat.py +440 -0
  182. aethergraph/services/memory/facade/core.py +447 -0
  183. aethergraph/services/memory/facade/distillation.py +424 -0
  184. aethergraph/services/memory/facade/rag.py +410 -0
  185. aethergraph/services/memory/facade/results.py +315 -0
  186. aethergraph/services/memory/facade/retrieval.py +139 -0
  187. aethergraph/services/memory/facade/types.py +77 -0
  188. aethergraph/services/memory/facade/utils.py +43 -0
  189. aethergraph/services/memory/facade_dep.py +1539 -0
  190. aethergraph/services/memory/factory.py +9 -3
  191. aethergraph/services/memory/utils.py +10 -0
  192. aethergraph/services/metering/eventlog_metering.py +470 -0
  193. aethergraph/services/metering/noop.py +25 -4
  194. aethergraph/services/rag/__init__.py +0 -0
  195. aethergraph/services/rag/facade.py +279 -23
  196. aethergraph/services/rag/index_factory.py +2 -2
  197. aethergraph/services/rag/node_rag.py +317 -0
  198. aethergraph/services/rate_limit/inmem_rate_limit.py +24 -0
  199. aethergraph/services/registry/__init__.py +0 -0
  200. aethergraph/services/registry/agent_app_meta.py +419 -0
  201. aethergraph/services/registry/registry_key.py +1 -1
  202. aethergraph/services/registry/unified_registry.py +74 -6
  203. aethergraph/services/scope/scope.py +159 -0
  204. aethergraph/services/scope/scope_factory.py +164 -0
  205. aethergraph/services/state_stores/serialize.py +5 -0
  206. aethergraph/services/state_stores/utils.py +2 -1
  207. aethergraph/services/viz/__init__.py +0 -0
  208. aethergraph/services/viz/facade.py +413 -0
  209. aethergraph/services/viz/viz_service.py +69 -0
  210. aethergraph/storage/artifacts/artifact_index_jsonl.py +180 -0
  211. aethergraph/storage/artifacts/artifact_index_sqlite.py +426 -0
  212. aethergraph/storage/artifacts/cas_store.py +422 -0
  213. aethergraph/storage/artifacts/fs_cas.py +18 -0
  214. aethergraph/storage/artifacts/s3_cas.py +14 -0
  215. aethergraph/storage/artifacts/utils.py +124 -0
  216. aethergraph/storage/blob/fs_blob.py +86 -0
  217. aethergraph/storage/blob/s3_blob.py +115 -0
  218. aethergraph/storage/continuation_store/fs_cont.py +283 -0
  219. aethergraph/storage/continuation_store/inmem_cont.py +146 -0
  220. aethergraph/storage/continuation_store/kvdoc_cont.py +261 -0
  221. aethergraph/storage/docstore/fs_doc.py +63 -0
  222. aethergraph/storage/docstore/sqlite_doc.py +31 -0
  223. aethergraph/storage/docstore/sqlite_doc_sync.py +90 -0
  224. aethergraph/storage/eventlog/fs_event.py +136 -0
  225. aethergraph/storage/eventlog/sqlite_event.py +47 -0
  226. aethergraph/storage/eventlog/sqlite_event_sync.py +178 -0
  227. aethergraph/storage/factory.py +432 -0
  228. aethergraph/storage/fs_utils.py +28 -0
  229. aethergraph/storage/graph_state_store/state_store.py +64 -0
  230. aethergraph/storage/kv/inmem_kv.py +103 -0
  231. aethergraph/storage/kv/layered_kv.py +52 -0
  232. aethergraph/storage/kv/sqlite_kv.py +39 -0
  233. aethergraph/storage/kv/sqlite_kv_sync.py +98 -0
  234. aethergraph/storage/memory/event_persist.py +68 -0
  235. aethergraph/storage/memory/fs_persist.py +118 -0
  236. aethergraph/{services/memory/hotlog_kv.py → storage/memory/hotlog.py} +8 -2
  237. aethergraph/{services → storage}/memory/indices.py +31 -7
  238. aethergraph/storage/metering/meter_event.py +55 -0
  239. aethergraph/storage/runs/doc_store.py +280 -0
  240. aethergraph/storage/runs/inmen_store.py +82 -0
  241. aethergraph/storage/runs/sqlite_run_store.py +403 -0
  242. aethergraph/storage/sessions/doc_store.py +183 -0
  243. aethergraph/storage/sessions/inmem_store.py +110 -0
  244. aethergraph/storage/sessions/sqlite_session_store.py +399 -0
  245. aethergraph/storage/vector_index/chroma_index.py +138 -0
  246. aethergraph/storage/vector_index/faiss_index.py +179 -0
  247. aethergraph/storage/vector_index/sqlite_index.py +187 -0
  248. {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a2.dist-info}/METADATA +138 -31
  249. aethergraph-0.1.0a2.dist-info/RECORD +356 -0
  250. aethergraph-0.1.0a2.dist-info/entry_points.txt +3 -0
  251. aethergraph/services/artifacts/factory.py +0 -35
  252. aethergraph/services/artifacts/fs_store.py +0 -656
  253. aethergraph/services/artifacts/jsonl_index.py +0 -123
  254. aethergraph/services/artifacts/sqlite_index.py +0 -209
  255. aethergraph/services/memory/distillers/episode.py +0 -116
  256. aethergraph/services/memory/distillers/rolling.py +0 -74
  257. aethergraph/services/memory/facade.py +0 -633
  258. aethergraph/services/memory/persist_fs.py +0 -40
  259. aethergraph/services/rag/index/base.py +0 -27
  260. aethergraph/services/rag/index/faiss_index.py +0 -121
  261. aethergraph/services/rag/index/sqlite_index.py +0 -134
  262. aethergraph-0.1.0a1.dist-info/RECORD +0 -182
  263. aethergraph-0.1.0a1.dist-info/entry_points.txt +0 -2
  264. {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a2.dist-info}/WHEEL +0 -0
  265. {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a2.dist-info}/licenses/LICENSE +0 -0
  266. {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a2.dist-info}/licenses/NOTICE +0 -0
  267. {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,535 @@
1
+ # Schemas for request and response bodies used in the API.
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from enum import Enum
7
+ from typing import Any, Literal
8
+
9
+ from pydantic import BaseModel, Field, RootModel
10
+
11
+ from aethergraph.core.runtime.run_types import RunImportance, RunOrigin, RunVisibility, SessionKind
12
+
13
+
14
+ # --------- Graphs ---------
15
+ class GraphListItem(BaseModel):
16
+ graph_id: str
17
+ name: str
18
+ description: str | None = None
19
+ inputs: list[str] = []
20
+ outputs: list[str] = []
21
+ tags: list[str] = []
22
+ kind: str | None = None # "graph" | "graphfn"
23
+ flow_id: str | None = None
24
+ entrypoint: bool | None = None
25
+
26
+
27
+ class GraphNodeInfo(BaseModel):
28
+ id: str
29
+ type: str | None = None
30
+ tool_name: str | None = None
31
+ tool_version: str | None = None
32
+ expected_inputs: list[str] = []
33
+ expected_outputs: list[str] = []
34
+ output_keys: list[str] = []
35
+
36
+
37
+ class GraphEdgeInfo(BaseModel):
38
+ source: str
39
+ target: str
40
+
41
+
42
+ class GraphDetail(BaseModel):
43
+ graph_id: str
44
+ name: str
45
+ description: str | None = None
46
+ inputs: list[str]
47
+ outputs: list[str]
48
+ tags: list[str] = []
49
+
50
+ kind: str | None = None # "graph" | "graphfn"
51
+ flow_id: str | None = None
52
+ entrypoint: bool | None = None
53
+ nodes: list[GraphNodeInfo] = []
54
+ edges: list[GraphEdgeInfo] = []
55
+
56
+
57
+ # --------- Runs ---------
58
+
59
+
60
+ class RunStatus(str, Enum):
61
+ pending = "pending"
62
+ running = "running"
63
+ succeeded = "succeeded"
64
+ failed = "failed"
65
+ waiting = "waiting"
66
+ canceled = "canceled"
67
+ cancellation_requested = "cancellation_requested"
68
+
69
+
70
+ class RunSummary(BaseModel):
71
+ run_id: str
72
+ graph_id: str
73
+ status: RunStatus
74
+ started_at: datetime | None = None
75
+ finished_at: datetime | None = None
76
+ session_id: str | None = None
77
+ tags: list[str] = []
78
+ user_id: str | None = None
79
+ org_id: str | None = None
80
+ graph_kind: str | None = None
81
+ flow_id: str | None = None
82
+ entrypoint: bool | None = None
83
+
84
+ meta: dict[str, Any] = Field(default_factory=dict)
85
+
86
+ # Python attribute names are snake_case, JSON keys are camelCase
87
+ app_id: str | None = Field(default=None, alias="appId")
88
+ app_name: str | None = Field(default=None, alias="appName")
89
+ agent_id: str | None = Field(default=None, alias="agentId")
90
+
91
+ # origin/visibility/importance could go here if desired
92
+ origin: RunOrigin | None = None
93
+ visibility: RunVisibility | None = None
94
+ importance: RunImportance | None = None
95
+
96
+ # artifact stats for UI
97
+ artifact_count: int | None = None
98
+ last_artifact_at: datetime | None = None
99
+
100
+ class Config:
101
+ populate_by_name = True # allows setting via app_id/app_name in Python
102
+
103
+
104
+ class RunCreateRequest(BaseModel):
105
+ run_id: str | None = None
106
+ inputs: dict[str, Any]
107
+ run_config: dict[str, Any] = {}
108
+ tags: list[str] = []
109
+ session_id: str | None = None
110
+
111
+ # origin/visibility/importance could go here if desired
112
+ origin: RunOrigin | None = None
113
+ visibility: RunVisibility | None = None
114
+ importance: RunImportance | None = None
115
+
116
+ # agent / app info
117
+ agent_id: str | None = Field(default=None, alias="agentId")
118
+ app_id: str | None = Field(default=None, alias="appId")
119
+ app_name: str | None = Field(default=None, alias="appName")
120
+
121
+ class Config:
122
+ populate_by_name = True # allows setting via app_id/app_name in Python
123
+
124
+
125
+ class RunCreateResponse(BaseModel):
126
+ run_id: str
127
+ graph_id: str
128
+ status: RunStatus
129
+ outputs: dict[str, Any] | None = None
130
+ has_waits: bool
131
+ continuations: list[dict[str, Any]] = []
132
+ started_at: datetime | None = None
133
+ finished_at: datetime | None = None
134
+
135
+
136
+ # for channel events emitted during a run
137
+ class RunChannelEvent(BaseModel):
138
+ id: str
139
+ run_id: str
140
+ type: str # original OutEvent.type
141
+ text: str | None
142
+ buttons: list[dict[str, Any]]
143
+ file: dict[str, Any] | None
144
+ meta: dict[str, Any]
145
+ ts: float # unix timestamp
146
+
147
+
148
+ class NodeSnapshot(BaseModel):
149
+ node_id: str
150
+ tool_name: str | None = None
151
+ status: RunStatus
152
+ started_at: datetime | None = None
153
+ finished_at: datetime | None = None
154
+ outputs: dict[str, Any] | None = None
155
+ error: str | None = None
156
+
157
+
158
+ class EdgeSnapshot(BaseModel):
159
+ source: str
160
+ target: str
161
+
162
+
163
+ class RunSnapshot(BaseModel):
164
+ run_id: str
165
+ graph_id: str
166
+ nodes: list[NodeSnapshot]
167
+ edges: list[EdgeSnapshot]
168
+ graph_kind: str | None = None
169
+ flow_id: str | None = None
170
+ entrypoint: bool | None = None
171
+
172
+
173
+ class RunListResponse(BaseModel):
174
+ runs: list[RunSummary]
175
+ next_cursor: str | None = None
176
+
177
+
178
+ # --------- Memory ---------
179
+ class MemoryEvent(BaseModel):
180
+ event_id: str
181
+ scope_id: str
182
+ kind: str
183
+ tags: list[str] = Field(default_factory=list)
184
+ created_at: datetime
185
+ data: dict[str, Any] | None = None
186
+
187
+
188
+ class MemoryEventListResponse(BaseModel):
189
+ events: list[MemoryEvent]
190
+ next_cursor: str | None = None
191
+
192
+
193
+ # ---------- Summaries ----------
194
+
195
+
196
+ class MemorySummaryEntry(BaseModel):
197
+ summary_id: str
198
+ scope_id: str
199
+ summary_tag: str
200
+ created_at: datetime
201
+ time_from: datetime
202
+ time_to: datetime
203
+ text: str
204
+ metadata: dict[str, Any] = Field(default_factory=dict)
205
+
206
+
207
+ class MemorySummaryListResponse(BaseModel):
208
+ summaries: list[MemorySummaryEntry]
209
+ next_cursor: str | None = None
210
+
211
+
212
+ # ---------- Search ----------
213
+
214
+
215
+ class MemorySearchRequest(BaseModel):
216
+ query: str
217
+ scope_id: str | None = None
218
+ top_k: int = 10
219
+
220
+
221
+ class MemorySearchHit(BaseModel):
222
+ score: float
223
+ event: MemoryEvent | None = None
224
+ summary: MemorySummaryEntry | None = None
225
+
226
+
227
+ class MemorySearchResponse(BaseModel):
228
+ hits: list[MemorySearchHit]
229
+
230
+
231
+ # --------- Artifacts ---------
232
+ class ArtifactMeta(BaseModel):
233
+ artifact_id: str
234
+ kind: str
235
+ mime_type: str | None = None
236
+ size: int | None = None
237
+ scope_id: str | None = None
238
+ tags: list[str] = []
239
+ created_at: datetime
240
+ uri: str | None = None
241
+ pinned: bool = False
242
+ preview_uri: str | None = None
243
+
244
+ # Associated run / graph / node
245
+ run_id: str | None = None
246
+ graph_id: str | None = None
247
+ node_id: str | None = None
248
+ session_id: str | None = None
249
+
250
+ # human-facing
251
+ filename: str | None = None
252
+
253
+
254
+ class ArtifactListResponse(BaseModel):
255
+ artifacts: list[ArtifactMeta]
256
+ next_cursor: str | None = None
257
+
258
+
259
+ class ArtifactSearchRequest(BaseModel):
260
+ # Optional semantic / text query (for future embedding search)
261
+ query: str | None = None
262
+
263
+ # Common filters
264
+ scope_id: str | None = None
265
+ kind: str | None = None
266
+ tags: list[str] | None = None
267
+
268
+ # Extra label filters that map directly to Artifact.labels
269
+ labels: dict[str, Any] = Field(default_factory=dict)
270
+
271
+ # Metric-based ranking
272
+ metric: str | None = None
273
+ mode: Literal["max", "min"] | None = None
274
+
275
+ # Pagination / result size
276
+ limit: int = 10
277
+
278
+ # If True, use index.best(...) and only return a single hit
279
+ best_only: bool = False
280
+
281
+
282
+ class ArtifactSearchHit(BaseModel):
283
+ score: float
284
+ artifact: ArtifactMeta | None = None
285
+
286
+
287
+ class ArtifactSearchResponse(BaseModel):
288
+ hits: list[ArtifactSearchHit]
289
+
290
+
291
+ # --------- channels ---------
292
+
293
+
294
+ class ChannelIngressRequest(BaseModel):
295
+ kind: str = "chat_user"
296
+ text: str | None = None
297
+ metadata: dict[str, Any] = {}
298
+
299
+
300
+ class ChannelEvent(BaseModel):
301
+ event_id: str
302
+ channel_id: str
303
+ kind: str
304
+ created_at: datetime
305
+ data: dict[str, Any]
306
+
307
+
308
+ class ChannelEventListResponse(BaseModel):
309
+ events: list[ChannelEvent]
310
+ next_cursor: str | None = None
311
+
312
+
313
+ # ---------- Misc ----------
314
+
315
+
316
+ class HealthResponse(BaseModel):
317
+ status: str
318
+ version: str
319
+
320
+
321
+ class ConfigLLMProvider(BaseModel):
322
+ name: str
323
+ model: str | None = None
324
+ enabled: bool = True
325
+
326
+
327
+ class ConfigResponse(BaseModel):
328
+ version: str
329
+ storage_backends: dict[str, str] = {}
330
+ llm_providers: list[ConfigLLMProvider] = []
331
+ features: dict[str, bool] = {}
332
+
333
+
334
+ # --------- Stats ---------
335
+ # ---------- Overview ----------
336
+
337
+
338
+ class StatsOverview(BaseModel):
339
+ llm_calls: int = Field(0, description="Total LLM calls in the window")
340
+ llm_prompt_tokens: int = Field(0, description="Total prompt tokens in the window")
341
+ llm_completion_tokens: int = Field(0, description="Total completion tokens in the window")
342
+
343
+ runs: int = Field(0, description="Total runs started in the window")
344
+ runs_succeeded: int = Field(0, description="Runs that completed successfully")
345
+ runs_failed: int = Field(0, description="Runs that failed")
346
+
347
+ artifacts: int = Field(0, description="Total artifacts recorded in the window")
348
+ artifact_bytes: int = Field(0, description="Total artifact payload size in bytes")
349
+
350
+ events: int = Field(0, description="Total metered memory events in the window")
351
+
352
+
353
+ # ---------- Graph stats ----------
354
+
355
+
356
+ class GraphStatsEntry(BaseModel):
357
+ runs: int = Field(0)
358
+ succeeded: int = Field(0)
359
+ failed: int = Field(0)
360
+ total_duration_s: float = Field(0.0)
361
+
362
+
363
+ class GraphStats(RootModel[dict[str, GraphStatsEntry]]):
364
+ """Map graph_id -> GraphStatsEntry"""
365
+
366
+ # no extra fields needed; RootModel handles serialization
367
+
368
+
369
+ # ---------- Memory stats ----------
370
+
371
+
372
+ class MemoryStats(RootModel[dict[str, dict[str, int]]]):
373
+ """Map memory_kind -> { 'count': int }"""
374
+
375
+
376
+ # ---------- Artifact stats ----------
377
+
378
+
379
+ class ArtifactStatsEntry(BaseModel):
380
+ count: int = 0
381
+ bytes: int = 0
382
+ pinned_count: int = 0
383
+ pinned_bytes: int = 0
384
+
385
+
386
+ class ArtifactStats(RootModel[dict[str, ArtifactStatsEntry]]):
387
+ """Map artifact_kind -> ArtifactStatsEntry"""
388
+
389
+
390
+ # ---------- LLM stats ----------
391
+
392
+
393
+ class LLMStatsEntry(BaseModel):
394
+ calls: int = 0
395
+ prompt_tokens: int = 0
396
+ completion_tokens: int = 0
397
+
398
+
399
+ class LLMStats(RootModel[dict[str, LLMStatsEntry]]):
400
+ """
401
+ Map of LLM model name → stats.
402
+
403
+ Example:
404
+ {
405
+ "gpt-4o-mini": {"calls": 5, "prompt_tokens": 1234, "completion_tokens": 567}
406
+ }
407
+ """
408
+
409
+
410
+ # ------ viz facade integration ------
411
+ VizKind = Literal["scalar", "vector", "matrix", "image"]
412
+ VizMode = Literal["append", "replace"]
413
+
414
+
415
+ class VizPoint(BaseModel):
416
+ step: int = Field(..., description="Iteration / timestep")
417
+ value: float | None = None
418
+ vector: list[float] | None = None
419
+ matrix: list[list[float]] | None = None
420
+ artifact_id: str | None = Field(
421
+ None,
422
+ description="Artifact ID for image frames (or future 3D payloads).",
423
+ )
424
+ created_at: datetime | None = None
425
+
426
+
427
+ class VizTrack(BaseModel):
428
+ track_id: str = Field(..., description="Developer-chosen ID, e.g. 'loss', 'design_shape'")
429
+ figure_id: str | None = Field(None, description="Optional panel/group ID, e.g. 'metrics_panel'")
430
+ node_id: str | None = Field(None, description="Node that emitted this track, if applicable")
431
+ viz_kind: VizKind
432
+ mode: VizMode = "append"
433
+ meta: dict[str, Any] | None = None
434
+ points: list[VizPoint]
435
+
436
+
437
+ class VizFigure(BaseModel):
438
+ figure_id: str | None = Field(
439
+ None,
440
+ description="Panel/group identifier; tracks with same figure_id are shown together",
441
+ )
442
+ tracks: list[VizTrack]
443
+
444
+
445
+ class RunVizResponse(BaseModel):
446
+ run_id: str
447
+ figures: list[VizFigure]
448
+
449
+
450
+ # -------------- Session Schemas --------------
451
+ class Session(BaseModel):
452
+ session_id: str
453
+ kind: SessionKind
454
+ title: str | None = None
455
+
456
+ user_id: str | None = None
457
+ org_id: str | None = None
458
+
459
+ source: str = "webui" # "webui", "sidecar", "api", "sdk", etc.
460
+ external_ref: str | None = None # e.g. chat ID, playground ID, notebook path, etc.
461
+
462
+ created_at: datetime
463
+ updated_at: datetime
464
+
465
+ # artifact stats for UI
466
+ artifact_count: int = 0
467
+ last_artifact_at: datetime | None = None
468
+
469
+
470
+ class SessionCreateRequest(BaseModel):
471
+ kind: SessionKind
472
+ title: str | None = None
473
+ external_ref: str | None = None
474
+
475
+
476
+ class SessionListResponse(BaseModel):
477
+ items: list[Session]
478
+ next_cursor: str | None = None
479
+
480
+
481
+ class SessionRunsResponse(BaseModel):
482
+ items: list[RunSummary]
483
+
484
+
485
+ class SessionChatFile(BaseModel):
486
+ url: str | None = None
487
+ name: str | None = None
488
+ mimetype: str | None = None
489
+ size: int | None = None
490
+ uri: str | None = None # optional, useful for artifact URIs
491
+
492
+
493
+ class SessionChatEvent(BaseModel):
494
+ id: str
495
+ session_id: str
496
+ type: str
497
+ text: str | None
498
+ buttons: list[dict[str, Any]]
499
+ file: SessionChatFile | None = None # legacy/single
500
+ files: list[SessionChatFile] | None = None # NEW: multi
501
+ meta: dict[str, Any]
502
+ ts: float
503
+ agent_id: str | None = None
504
+ upsert_key: str | None = None # for idempotent updates
505
+
506
+
507
+ class SessionUpdateRequest(BaseModel):
508
+ title: str | None = None
509
+ external_ref: str | None = None
510
+
511
+
512
+ # ------ Agent and App Schemas ------
513
+ class AgentDescriptor(BaseModel):
514
+ """
515
+ Lightweight wrapper for an agent's registry metadata.
516
+
517
+ We only enforce an `id` and keep the rest as a free-form `meta` dict
518
+ so we can evolve the UI without breaking older agents.
519
+ """
520
+
521
+ id: str
522
+ meta: dict[str, Any] = Field(default_factory=dict)
523
+
524
+
525
+ class AppDescriptor(BaseModel):
526
+ """
527
+ Lightweight wrapper for an app's registry metadata.
528
+
529
+ `graph_id` tells the frontend which graph to run when this app is launched.
530
+ Everything else lives inside a free-form `meta` dict for now.
531
+ """
532
+
533
+ id: str
534
+ graph_id: str
535
+ meta: dict[str, Any] = Field(default_factory=dict)