coco-framework 0.1.0__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 (400) hide show
  1. coco/__init__.py +3 -0
  2. coco/agents/__init__.py +9 -0
  3. coco/agents/_subagent_transformer.py +307 -0
  4. coco/agents/factory.py +2164 -0
  5. coco/agents/middleware/__init__.py +100 -0
  6. coco/agents/middleware/_execution.py +385 -0
  7. coco/agents/middleware/_redaction.py +454 -0
  8. coco/agents/middleware/_retry.py +134 -0
  9. coco/agents/middleware/_trace_policy.py +61 -0
  10. coco/agents/middleware/context_editing.py +306 -0
  11. coco/agents/middleware/file_search.py +433 -0
  12. coco/agents/middleware/human_in_the_loop.py +680 -0
  13. coco/agents/middleware/internal_call_transformer.py +108 -0
  14. coco/agents/middleware/model_call_limit.py +267 -0
  15. coco/agents/middleware/model_fallback.py +417 -0
  16. coco/agents/middleware/model_retry.py +327 -0
  17. coco/agents/middleware/pii.py +878 -0
  18. coco/agents/middleware/provider_tool_search.py +307 -0
  19. coco/agents/middleware/shell_tool.py +949 -0
  20. coco/agents/middleware/summarization.py +910 -0
  21. coco/agents/middleware/todo.py +357 -0
  22. coco/agents/middleware/tool_call_limit.py +495 -0
  23. coco/agents/middleware/tool_emulator.py +251 -0
  24. coco/agents/middleware/tool_error.py +209 -0
  25. coco/agents/middleware/tool_retry.py +421 -0
  26. coco/agents/middleware/tool_selection.py +515 -0
  27. coco/agents/middleware/types.py +2201 -0
  28. coco/agents/structured_output.py +472 -0
  29. coco/chat_models/__init__.py +7 -0
  30. coco/chat_models/base.py +1082 -0
  31. coco/embeddings/__init__.py +18 -0
  32. coco/embeddings/base.py +279 -0
  33. coco/mcp/__init__.py +36 -0
  34. coco/mcp/adapter.py +245 -0
  35. coco/mcp/elicitation.py +394 -0
  36. coco/mcp/tools.py +307 -0
  37. coco/messages/__init__.py +73 -0
  38. coco/py.typed +0 -0
  39. coco/rate_limiters/__init__.py +13 -0
  40. coco/tools/__init__.py +22 -0
  41. coco/tools/tool_node.py +20 -0
  42. coco_anthropic/__init__.py +15 -0
  43. coco_anthropic/_client_utils.py +81 -0
  44. coco_anthropic/_compat.py +228 -0
  45. coco_anthropic/_sdk_compat.py +124 -0
  46. coco_anthropic/_version.py +3 -0
  47. coco_anthropic/chat_models.py +3349 -0
  48. coco_anthropic/data/__init__.py +1 -0
  49. coco_anthropic/data/_profiles.py +491 -0
  50. coco_anthropic/data/profile_augmentations.toml +69 -0
  51. coco_anthropic/experimental.py +140 -0
  52. coco_anthropic/llms.py +428 -0
  53. coco_anthropic/middleware/__init__.py +25 -0
  54. coco_anthropic/middleware/anthropic_tools.py +1197 -0
  55. coco_anthropic/middleware/bash.py +84 -0
  56. coco_anthropic/middleware/file_search.py +360 -0
  57. coco_anthropic/middleware/prompt_caching.py +276 -0
  58. coco_anthropic/output_parsers.py +93 -0
  59. coco_anthropic/py.typed +0 -0
  60. coco_core/__init__.py +20 -0
  61. coco_core/_api/__init__.py +87 -0
  62. coco_core/_api/beta_decorator.py +266 -0
  63. coco_core/_api/deprecation.py +637 -0
  64. coco_core/_api/internal.py +23 -0
  65. coco_core/_api/path.py +50 -0
  66. coco_core/_import_utils.py +41 -0
  67. coco_core/_protocol.py +625 -0
  68. coco_core/_security/__init__.py +36 -0
  69. coco_core/_security/_exceptions.py +9 -0
  70. coco_core/_security/_policy.py +313 -0
  71. coco_core/_security/_ssrf_protection.py +155 -0
  72. coco_core/_security/_transport.py +254 -0
  73. coco_core/agents.py +258 -0
  74. coco_core/caches.py +272 -0
  75. coco_core/callbacks/__init__.py +132 -0
  76. coco_core/callbacks/base.py +1229 -0
  77. coco_core/callbacks/file.py +266 -0
  78. coco_core/callbacks/manager.py +2826 -0
  79. coco_core/callbacks/stdout.py +123 -0
  80. coco_core/callbacks/streaming_stdout.py +154 -0
  81. coco_core/callbacks/usage.py +124 -0
  82. coco_core/chat_history.py +267 -0
  83. coco_core/chat_loaders.py +26 -0
  84. coco_core/chat_sessions.py +19 -0
  85. coco_core/cross_encoders.py +18 -0
  86. coco_core/document_loaders/__init__.py +36 -0
  87. coco_core/document_loaders/base.py +155 -0
  88. coco_core/document_loaders/blob_loaders.py +38 -0
  89. coco_core/documents/__init__.py +55 -0
  90. coco_core/documents/base.py +347 -0
  91. coco_core/documents/compressor.py +74 -0
  92. coco_core/documents/transformers.py +79 -0
  93. coco_core/embeddings/__init__.py +31 -0
  94. coco_core/embeddings/embeddings.py +78 -0
  95. coco_core/embeddings/fake.py +129 -0
  96. coco_core/env.py +22 -0
  97. coco_core/example_selectors/__init__.py +47 -0
  98. coco_core/example_selectors/base.py +60 -0
  99. coco_core/example_selectors/length_based.py +131 -0
  100. coco_core/example_selectors/semantic_similarity.py +366 -0
  101. coco_core/exceptions.py +166 -0
  102. coco_core/globals.py +72 -0
  103. coco_core/indexing/__init__.py +53 -0
  104. coco_core/indexing/api.py +954 -0
  105. coco_core/indexing/base.py +661 -0
  106. coco_core/indexing/in_memory.py +104 -0
  107. coco_core/language_models/__init__.py +116 -0
  108. coco_core/language_models/_compat_bridge.py +844 -0
  109. coco_core/language_models/_utils.py +343 -0
  110. coco_core/language_models/base.py +500 -0
  111. coco_core/language_models/chat_model_stream.py +1525 -0
  112. coco_core/language_models/chat_models.py +2748 -0
  113. coco_core/language_models/fake.py +137 -0
  114. coco_core/language_models/fake_chat_models.py +396 -0
  115. coco_core/language_models/llms.py +1569 -0
  116. coco_core/language_models/model_profile.py +183 -0
  117. coco_core/load/__init__.py +44 -0
  118. coco_core/load/_validation.py +191 -0
  119. coco_core/load/dump.py +120 -0
  120. coco_core/load/load.py +828 -0
  121. coco_core/load/mapping.py +1097 -0
  122. coco_core/load/serializable.py +406 -0
  123. coco_core/messages/__init__.py +198 -0
  124. coco_core/messages/ai.py +854 -0
  125. coco_core/messages/base.py +518 -0
  126. coco_core/messages/block_translators/__init__.py +112 -0
  127. coco_core/messages/block_translators/anthropic.py +534 -0
  128. coco_core/messages/block_translators/bedrock.py +108 -0
  129. coco_core/messages/block_translators/bedrock_converse.py +329 -0
  130. coco_core/messages/block_translators/coco_v0.py +303 -0
  131. coco_core/messages/block_translators/google_genai.py +610 -0
  132. coco_core/messages/block_translators/google_vertexai.py +21 -0
  133. coco_core/messages/block_translators/groq.py +157 -0
  134. coco_core/messages/block_translators/openai.py +1089 -0
  135. coco_core/messages/chat.py +64 -0
  136. coco_core/messages/content.py +1488 -0
  137. coco_core/messages/function.py +62 -0
  138. coco_core/messages/human.py +70 -0
  139. coco_core/messages/modifier.py +33 -0
  140. coco_core/messages/system.py +70 -0
  141. coco_core/messages/tool.py +418 -0
  142. coco_core/messages/utils.py +2442 -0
  143. coco_core/output_parsers/__init__.py +101 -0
  144. coco_core/output_parsers/base.py +361 -0
  145. coco_core/output_parsers/format_instructions.py +16 -0
  146. coco_core/output_parsers/json.py +139 -0
  147. coco_core/output_parsers/list.py +249 -0
  148. coco_core/output_parsers/openai_functions.py +324 -0
  149. coco_core/output_parsers/openai_tools.py +383 -0
  150. coco_core/output_parsers/pydantic.py +141 -0
  151. coco_core/output_parsers/string.py +63 -0
  152. coco_core/output_parsers/transform.py +175 -0
  153. coco_core/output_parsers/xml.py +301 -0
  154. coco_core/outputs/__init__.py +66 -0
  155. coco_core/outputs/chat_generation.py +147 -0
  156. coco_core/outputs/chat_result.py +39 -0
  157. coco_core/outputs/generation.py +80 -0
  158. coco_core/outputs/llm_result.py +112 -0
  159. coco_core/outputs/run_info.py +22 -0
  160. coco_core/prompt_values.py +161 -0
  161. coco_core/prompts/__init__.py +101 -0
  162. coco_core/prompts/base.py +508 -0
  163. coco_core/prompts/chat.py +1495 -0
  164. coco_core/prompts/dict.py +177 -0
  165. coco_core/prompts/few_shot.py +483 -0
  166. coco_core/prompts/few_shot_with_templates.py +239 -0
  167. coco_core/prompts/image.py +177 -0
  168. coco_core/prompts/loading.py +296 -0
  169. coco_core/prompts/message.py +97 -0
  170. coco_core/prompts/prompt.py +312 -0
  171. coco_core/prompts/string.py +399 -0
  172. coco_core/prompts/structured.py +214 -0
  173. coco_core/py.typed +0 -0
  174. coco_core/rate_limiters.py +254 -0
  175. coco_core/retrievers.py +328 -0
  176. coco_core/runnables/__init__.py +136 -0
  177. coco_core/runnables/base.py +6725 -0
  178. coco_core/runnables/branch.py +457 -0
  179. coco_core/runnables/config.py +712 -0
  180. coco_core/runnables/configurable.py +710 -0
  181. coco_core/runnables/fallbacks.py +663 -0
  182. coco_core/runnables/graph.py +741 -0
  183. coco_core/runnables/graph_ascii.py +366 -0
  184. coco_core/runnables/graph_mermaid.py +503 -0
  185. coco_core/runnables/graph_png.py +215 -0
  186. coco_core/runnables/history.py +631 -0
  187. coco_core/runnables/passthrough.py +849 -0
  188. coco_core/runnables/retry.py +379 -0
  189. coco_core/runnables/router.py +239 -0
  190. coco_core/runnables/schema.py +188 -0
  191. coco_core/runnables/utils.py +798 -0
  192. coco_core/stores.py +291 -0
  193. coco_core/structured_query.py +203 -0
  194. coco_core/sys_info.py +154 -0
  195. coco_core/tools/__init__.py +95 -0
  196. coco_core/tools/base.py +1948 -0
  197. coco_core/tools/convert.py +497 -0
  198. coco_core/tools/render.py +67 -0
  199. coco_core/tools/retriever.py +94 -0
  200. coco_core/tools/simple.py +208 -0
  201. coco_core/tools/structured.py +322 -0
  202. coco_core/tracers/__init__.py +47 -0
  203. coco_core/tracers/_compat.py +95 -0
  204. coco_core/tracers/_context.py +337 -0
  205. coco_core/tracers/_streaming.py +53 -0
  206. coco_core/tracers/base.py +955 -0
  207. coco_core/tracers/coco.py +279 -0
  208. coco_core/tracers/context.py +205 -0
  209. coco_core/tracers/core.py +766 -0
  210. coco_core/tracers/event_stream.py +1101 -0
  211. coco_core/tracers/log_stream.py +765 -0
  212. coco_core/tracers/memory_stream.py +200 -0
  213. coco_core/tracers/root_listeners.py +130 -0
  214. coco_core/tracers/run_collector.py +40 -0
  215. coco_core/tracers/schemas.py +14 -0
  216. coco_core/tracers/stdout.py +205 -0
  217. coco_core/utils/__init__.py +111 -0
  218. coco_core/utils/_gateway.py +274 -0
  219. coco_core/utils/_merge.py +218 -0
  220. coco_core/utils/aiter.py +357 -0
  221. coco_core/utils/env.py +86 -0
  222. coco_core/utils/formatting.py +80 -0
  223. coco_core/utils/function_calling.py +869 -0
  224. coco_core/utils/html.py +132 -0
  225. coco_core/utils/image.py +15 -0
  226. coco_core/utils/input.py +82 -0
  227. coco_core/utils/interactive_env.py +12 -0
  228. coco_core/utils/iter.py +229 -0
  229. coco_core/utils/json.py +230 -0
  230. coco_core/utils/json_schema.py +273 -0
  231. coco_core/utils/mustache.py +706 -0
  232. coco_core/utils/pydantic.py +631 -0
  233. coco_core/utils/strings.py +69 -0
  234. coco_core/utils/usage.py +61 -0
  235. coco_core/utils/utils.py +528 -0
  236. coco_core/utils/uuid.py +57 -0
  237. coco_core/vectorstores/__init__.py +53 -0
  238. coco_core/vectorstores/base.py +1111 -0
  239. coco_core/vectorstores/in_memory.py +546 -0
  240. coco_core/vectorstores/utils.py +163 -0
  241. coco_core/version.py +3 -0
  242. coco_framework-0.1.0.dist-info/METADATA +184 -0
  243. coco_framework-0.1.0.dist-info/RECORD +400 -0
  244. coco_framework-0.1.0.dist-info/WHEEL +4 -0
  245. coco_framework-0.1.0.dist-info/licenses/LICENSE +24 -0
  246. coco_framework-0.1.0.dist-info/licenses/NOTICE +15 -0
  247. coco_graph/_internal/__init__.py +4 -0
  248. coco_graph/_internal/_cache.py +31 -0
  249. coco_graph/_internal/_config.py +474 -0
  250. coco_graph/_internal/_constants.py +140 -0
  251. coco_graph/_internal/_fields.py +213 -0
  252. coco_graph/_internal/_future.py +220 -0
  253. coco_graph/_internal/_pydantic.py +275 -0
  254. coco_graph/_internal/_queue.py +124 -0
  255. coco_graph/_internal/_replay.py +90 -0
  256. coco_graph/_internal/_retry.py +29 -0
  257. coco_graph/_internal/_runnable.py +969 -0
  258. coco_graph/_internal/_scratchpad.py +19 -0
  259. coco_graph/_internal/_serde.py +253 -0
  260. coco_graph/_internal/_timeout.py +25 -0
  261. coco_graph/_internal/_typing.py +54 -0
  262. coco_graph/cache/base/__init__.py +48 -0
  263. coco_graph/cache/base/py.typed +0 -0
  264. coco_graph/cache/memory/__init__.py +73 -0
  265. coco_graph/cache/redis/__init__.py +144 -0
  266. coco_graph/cache/sqlite/__init__.py +120 -0
  267. coco_graph/callbacks.py +394 -0
  268. coco_graph/channels/__init__.py +29 -0
  269. coco_graph/channels/any_value.py +72 -0
  270. coco_graph/channels/base.py +121 -0
  271. coco_graph/channels/binop.py +155 -0
  272. coco_graph/channels/delta.py +202 -0
  273. coco_graph/channels/ephemeral_value.py +79 -0
  274. coco_graph/channels/last_value.py +151 -0
  275. coco_graph/channels/named_barrier_value.py +167 -0
  276. coco_graph/channels/topic.py +94 -0
  277. coco_graph/channels/untracked_value.py +73 -0
  278. coco_graph/checkpoint/base/__init__.py +861 -0
  279. coco_graph/checkpoint/base/id.py +109 -0
  280. coco_graph/checkpoint/base/py.typed +0 -0
  281. coco_graph/checkpoint/memory/__init__.py +698 -0
  282. coco_graph/checkpoint/memory/py.typed +0 -0
  283. coco_graph/checkpoint/postgres/__init__.py +602 -0
  284. coco_graph/checkpoint/postgres/_ainternal.py +23 -0
  285. coco_graph/checkpoint/postgres/_internal.py +21 -0
  286. coco_graph/checkpoint/postgres/aio.py +691 -0
  287. coco_graph/checkpoint/postgres/base.py +666 -0
  288. coco_graph/checkpoint/postgres/py.typed +0 -0
  289. coco_graph/checkpoint/postgres/shallow.py +967 -0
  290. coco_graph/checkpoint/serde/__init__.py +0 -0
  291. coco_graph/checkpoint/serde/_msgpack.py +97 -0
  292. coco_graph/checkpoint/serde/base.py +64 -0
  293. coco_graph/checkpoint/serde/encrypted.py +80 -0
  294. coco_graph/checkpoint/serde/event_hooks.py +52 -0
  295. coco_graph/checkpoint/serde/jsonplus.py +883 -0
  296. coco_graph/checkpoint/serde/py.typed +0 -0
  297. coco_graph/checkpoint/serde/types.py +68 -0
  298. coco_graph/checkpoint/sqlite/__init__.py +645 -0
  299. coco_graph/checkpoint/sqlite/_delta.py +172 -0
  300. coco_graph/checkpoint/sqlite/aio.py +738 -0
  301. coco_graph/checkpoint/sqlite/py.typed +0 -0
  302. coco_graph/checkpoint/sqlite/utils.py +116 -0
  303. coco_graph/config.py +196 -0
  304. coco_graph/constants.py +64 -0
  305. coco_graph/errors.py +241 -0
  306. coco_graph/func/__init__.py +620 -0
  307. coco_graph/graph/__init__.py +12 -0
  308. coco_graph/graph/_branch.py +225 -0
  309. coco_graph/graph/_node.py +103 -0
  310. coco_graph/graph/message.py +437 -0
  311. coco_graph/graph/state.py +1978 -0
  312. coco_graph/graph/ui.py +227 -0
  313. coco_graph/managed/__init__.py +3 -0
  314. coco_graph/managed/base.py +31 -0
  315. coco_graph/managed/is_last_step.py +24 -0
  316. coco_graph/prebuilt/__init__.py +23 -0
  317. coco_graph/prebuilt/_tool_call_stream.py +117 -0
  318. coco_graph/prebuilt/_tool_call_transformer.py +165 -0
  319. coco_graph/prebuilt/chat_agent_executor.py +1015 -0
  320. coco_graph/prebuilt/interrupt.py +105 -0
  321. coco_graph/prebuilt/py.typed +0 -0
  322. coco_graph/prebuilt/tool_node.py +2030 -0
  323. coco_graph/prebuilt/tool_validator.py +221 -0
  324. coco_graph/pregel/__init__.py +3 -0
  325. coco_graph/pregel/_algo.py +1460 -0
  326. coco_graph/pregel/_call.py +298 -0
  327. coco_graph/pregel/_checkpoint.py +331 -0
  328. coco_graph/pregel/_config.py +0 -0
  329. coco_graph/pregel/_draw.py +294 -0
  330. coco_graph/pregel/_executor.py +223 -0
  331. coco_graph/pregel/_io.py +174 -0
  332. coco_graph/pregel/_log.py +3 -0
  333. coco_graph/pregel/_loop.py +1988 -0
  334. coco_graph/pregel/_messages.py +461 -0
  335. coco_graph/pregel/_read.py +312 -0
  336. coco_graph/pregel/_retry.py +854 -0
  337. coco_graph/pregel/_runner.py +941 -0
  338. coco_graph/pregel/_tools.py +268 -0
  339. coco_graph/pregel/_utils.py +221 -0
  340. coco_graph/pregel/_validate.py +120 -0
  341. coco_graph/pregel/_write.py +192 -0
  342. coco_graph/pregel/debug.py +302 -0
  343. coco_graph/pregel/main.py +4364 -0
  344. coco_graph/pregel/protocol.py +288 -0
  345. coco_graph/pregel/types.py +38 -0
  346. coco_graph/py.typed +0 -0
  347. coco_graph/runtime.py +350 -0
  348. coco_graph/store/base/__init__.py +1322 -0
  349. coco_graph/store/base/batch.py +371 -0
  350. coco_graph/store/base/embed.py +436 -0
  351. coco_graph/store/base/py.typed +0 -0
  352. coco_graph/store/memory/__init__.py +592 -0
  353. coco_graph/store/memory/py.typed +0 -0
  354. coco_graph/store/postgres/__init__.py +4 -0
  355. coco_graph/store/postgres/aio.py +592 -0
  356. coco_graph/store/postgres/base.py +1480 -0
  357. coco_graph/store/postgres/py.typed +0 -0
  358. coco_graph/store/sqlite/__init__.py +4 -0
  359. coco_graph/store/sqlite/aio.py +632 -0
  360. coco_graph/store/sqlite/base.py +1514 -0
  361. coco_graph/stream/__init__.py +45 -0
  362. coco_graph/stream/_convert.py +32 -0
  363. coco_graph/stream/_mux.py +523 -0
  364. coco_graph/stream/_types.py +330 -0
  365. coco_graph/stream/run_stream.py +735 -0
  366. coco_graph/stream/stream_channel.py +341 -0
  367. coco_graph/stream/transformers.py +1039 -0
  368. coco_graph/types.py +1079 -0
  369. coco_graph/typing.py +48 -0
  370. coco_graph/utils/__init__.py +1 -0
  371. coco_graph/utils/config.py +4 -0
  372. coco_graph/utils/runnable.py +3 -0
  373. coco_graph/version.py +13 -0
  374. coco_graph/warnings.py +69 -0
  375. coco_openai/__init__.py +20 -0
  376. coco_openai/_compat.py +45 -0
  377. coco_openai/_version.py +3 -0
  378. coco_openai/chat_models/__init__.py +6 -0
  379. coco_openai/chat_models/_client_utils.py +684 -0
  380. coco_openai/chat_models/_compat.py +525 -0
  381. coco_openai/chat_models/azure.py +1227 -0
  382. coco_openai/chat_models/base.py +5654 -0
  383. coco_openai/chat_models/codex.py +557 -0
  384. coco_openai/chatgpt_oauth.py +1063 -0
  385. coco_openai/data/__init__.py +1 -0
  386. coco_openai/data/_profiles.py +1655 -0
  387. coco_openai/data/profile_augmentations.toml +127 -0
  388. coco_openai/embeddings/__init__.py +6 -0
  389. coco_openai/embeddings/azure.py +240 -0
  390. coco_openai/embeddings/base.py +820 -0
  391. coco_openai/llms/__init__.py +6 -0
  392. coco_openai/llms/azure.py +249 -0
  393. coco_openai/llms/base.py +919 -0
  394. coco_openai/middleware/__init__.py +11 -0
  395. coco_openai/middleware/openai_moderation.py +484 -0
  396. coco_openai/output_parsers/__init__.py +9 -0
  397. coco_openai/output_parsers/tools.py +9 -0
  398. coco_openai/py.typed +0 -0
  399. coco_openai/tools/__init__.py +5 -0
  400. coco_openai/tools/custom_tool.py +111 -0
@@ -0,0 +1,288 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import abstractmethod
4
+ from collections.abc import AsyncIterator, Callable, Iterator, Sequence
5
+ from typing import Any, Generic, Literal, overload
6
+
7
+ from coco_core.runnables import Runnable, RunnableConfig
8
+ from coco_core.runnables.graph import Graph as DrawableGraph
9
+ from typing_extensions import Self
10
+
11
+ from coco_graph.types import (
12
+ All,
13
+ Command,
14
+ GraphOutput,
15
+ StateSnapshot,
16
+ StateUpdate,
17
+ StreamMode,
18
+ StreamPart,
19
+ )
20
+ from coco_graph.typing import ContextT, InputT, OutputT, StateT
21
+
22
+ __all__ = ("PregelProtocol", "StreamProtocol")
23
+
24
+
25
+ class PregelProtocol(Runnable[InputT, Any], Generic[StateT, ContextT, InputT, OutputT]):
26
+ @abstractmethod
27
+ def with_config(
28
+ self, config: RunnableConfig | None = None, **kwargs: Any
29
+ ) -> Self: ...
30
+
31
+ @abstractmethod
32
+ def get_graph(
33
+ self,
34
+ config: RunnableConfig | None = None,
35
+ *,
36
+ xray: int | bool = False,
37
+ ) -> DrawableGraph: ...
38
+
39
+ @abstractmethod
40
+ async def aget_graph(
41
+ self,
42
+ config: RunnableConfig | None = None,
43
+ *,
44
+ xray: int | bool = False,
45
+ ) -> DrawableGraph: ...
46
+
47
+ @abstractmethod
48
+ def get_state(
49
+ self, config: RunnableConfig, *, subgraphs: bool = False
50
+ ) -> StateSnapshot: ...
51
+
52
+ @abstractmethod
53
+ async def aget_state(
54
+ self, config: RunnableConfig, *, subgraphs: bool = False
55
+ ) -> StateSnapshot: ...
56
+
57
+ @abstractmethod
58
+ def get_state_history(
59
+ self,
60
+ config: RunnableConfig,
61
+ *,
62
+ filter: dict[str, Any] | None = None,
63
+ before: RunnableConfig | None = None,
64
+ limit: int | None = None,
65
+ ) -> Iterator[StateSnapshot]: ...
66
+
67
+ @abstractmethod
68
+ def aget_state_history(
69
+ self,
70
+ config: RunnableConfig,
71
+ *,
72
+ filter: dict[str, Any] | None = None,
73
+ before: RunnableConfig | None = None,
74
+ limit: int | None = None,
75
+ ) -> AsyncIterator[StateSnapshot]: ...
76
+
77
+ @abstractmethod
78
+ def bulk_update_state(
79
+ self,
80
+ config: RunnableConfig,
81
+ updates: Sequence[Sequence[StateUpdate]],
82
+ ) -> RunnableConfig: ...
83
+
84
+ @abstractmethod
85
+ async def abulk_update_state(
86
+ self,
87
+ config: RunnableConfig,
88
+ updates: Sequence[Sequence[StateUpdate]],
89
+ ) -> RunnableConfig: ...
90
+
91
+ @abstractmethod
92
+ def update_state(
93
+ self,
94
+ config: RunnableConfig,
95
+ values: dict[str, Any] | Any | None,
96
+ as_node: str | None = None,
97
+ ) -> RunnableConfig: ...
98
+
99
+ @abstractmethod
100
+ async def aupdate_state(
101
+ self,
102
+ config: RunnableConfig,
103
+ values: dict[str, Any] | Any | None,
104
+ as_node: str | None = None,
105
+ ) -> RunnableConfig: ...
106
+
107
+ @overload
108
+ @abstractmethod
109
+ def stream(
110
+ self,
111
+ input: InputT | Command | None,
112
+ config: RunnableConfig | None = None,
113
+ *,
114
+ context: ContextT | None = None,
115
+ stream_mode: StreamMode | list[StreamMode] | None = None,
116
+ interrupt_before: All | Sequence[str] | None = None,
117
+ interrupt_after: All | Sequence[str] | None = None,
118
+ subgraphs: bool = False,
119
+ version: Literal["v2"],
120
+ ) -> Iterator[StreamPart[StateT, OutputT]]: ...
121
+
122
+ @overload
123
+ @abstractmethod
124
+ def stream(
125
+ self,
126
+ input: InputT | Command | None,
127
+ config: RunnableConfig | None = None,
128
+ *,
129
+ context: ContextT | None = None,
130
+ stream_mode: StreamMode | list[StreamMode] | None = None,
131
+ interrupt_before: All | Sequence[str] | None = None,
132
+ interrupt_after: All | Sequence[str] | None = None,
133
+ subgraphs: bool = False,
134
+ version: Literal["v1"] = ...,
135
+ ) -> Iterator[dict[str, Any] | Any]: ...
136
+
137
+ @abstractmethod
138
+ def stream(
139
+ self,
140
+ input: InputT | Command | None,
141
+ config: RunnableConfig | None = None,
142
+ *,
143
+ context: ContextT | None = None,
144
+ stream_mode: StreamMode | list[StreamMode] | None = None,
145
+ interrupt_before: All | Sequence[str] | None = None,
146
+ interrupt_after: All | Sequence[str] | None = None,
147
+ subgraphs: bool = False,
148
+ version: Literal["v1", "v2"] = "v1",
149
+ ) -> Iterator[dict[str, Any] | Any]: ...
150
+
151
+ @overload
152
+ @abstractmethod
153
+ def astream(
154
+ self,
155
+ input: InputT | Command | None,
156
+ config: RunnableConfig | None = None,
157
+ *,
158
+ context: ContextT | None = None,
159
+ stream_mode: StreamMode | list[StreamMode] | None = None,
160
+ interrupt_before: All | Sequence[str] | None = None,
161
+ interrupt_after: All | Sequence[str] | None = None,
162
+ subgraphs: bool = False,
163
+ version: Literal["v2"],
164
+ ) -> AsyncIterator[StreamPart[StateT, OutputT]]: ...
165
+
166
+ @overload
167
+ @abstractmethod
168
+ def astream(
169
+ self,
170
+ input: InputT | Command | None,
171
+ config: RunnableConfig | None = None,
172
+ *,
173
+ context: ContextT | None = None,
174
+ stream_mode: StreamMode | list[StreamMode] | None = None,
175
+ interrupt_before: All | Sequence[str] | None = None,
176
+ interrupt_after: All | Sequence[str] | None = None,
177
+ subgraphs: bool = False,
178
+ version: Literal["v1"] = ...,
179
+ ) -> AsyncIterator[dict[str, Any] | Any]: ...
180
+
181
+ @abstractmethod
182
+ def astream(
183
+ self,
184
+ input: InputT | Command | None,
185
+ config: RunnableConfig | None = None,
186
+ *,
187
+ context: ContextT | None = None,
188
+ stream_mode: StreamMode | list[StreamMode] | None = None,
189
+ interrupt_before: All | Sequence[str] | None = None,
190
+ interrupt_after: All | Sequence[str] | None = None,
191
+ subgraphs: bool = False,
192
+ version: Literal["v1", "v2"] = "v1",
193
+ ) -> AsyncIterator[dict[str, Any] | Any]: ...
194
+
195
+ @overload
196
+ @abstractmethod
197
+ def invoke(
198
+ self,
199
+ input: InputT | Command | None,
200
+ config: RunnableConfig | None = None,
201
+ *,
202
+ context: ContextT | None = None,
203
+ interrupt_before: All | Sequence[str] | None = None,
204
+ interrupt_after: All | Sequence[str] | None = None,
205
+ version: Literal["v2"],
206
+ ) -> GraphOutput[OutputT]: ...
207
+
208
+ @overload
209
+ @abstractmethod
210
+ def invoke(
211
+ self,
212
+ input: InputT | Command | None,
213
+ config: RunnableConfig | None = None,
214
+ *,
215
+ context: ContextT | None = None,
216
+ interrupt_before: All | Sequence[str] | None = None,
217
+ interrupt_after: All | Sequence[str] | None = None,
218
+ version: Literal["v1"] = ...,
219
+ ) -> dict[str, Any] | Any: ...
220
+
221
+ @abstractmethod
222
+ def invoke(
223
+ self,
224
+ input: InputT | Command | None,
225
+ config: RunnableConfig | None = None,
226
+ *,
227
+ context: ContextT | None = None,
228
+ interrupt_before: All | Sequence[str] | None = None,
229
+ interrupt_after: All | Sequence[str] | None = None,
230
+ version: Literal["v1", "v2"] = "v1",
231
+ ) -> dict[str, Any] | Any: ...
232
+
233
+ @overload
234
+ @abstractmethod
235
+ async def ainvoke(
236
+ self,
237
+ input: InputT | Command | None,
238
+ config: RunnableConfig | None = None,
239
+ *,
240
+ context: ContextT | None = None,
241
+ interrupt_before: All | Sequence[str] | None = None,
242
+ interrupt_after: All | Sequence[str] | None = None,
243
+ version: Literal["v2"],
244
+ ) -> GraphOutput[OutputT]: ...
245
+
246
+ @overload
247
+ @abstractmethod
248
+ async def ainvoke(
249
+ self,
250
+ input: InputT | Command | None,
251
+ config: RunnableConfig | None = None,
252
+ *,
253
+ context: ContextT | None = None,
254
+ interrupt_before: All | Sequence[str] | None = None,
255
+ interrupt_after: All | Sequence[str] | None = None,
256
+ version: Literal["v1"] = ...,
257
+ ) -> dict[str, Any] | Any: ...
258
+
259
+ @abstractmethod
260
+ async def ainvoke(
261
+ self,
262
+ input: InputT | Command | None,
263
+ config: RunnableConfig | None = None,
264
+ *,
265
+ context: ContextT | None = None,
266
+ interrupt_before: All | Sequence[str] | None = None,
267
+ interrupt_after: All | Sequence[str] | None = None,
268
+ version: Literal["v1", "v2"] = "v1",
269
+ ) -> dict[str, Any] | Any: ...
270
+
271
+
272
+ StreamChunk = tuple[tuple[str, ...], str, Any]
273
+
274
+
275
+ class StreamProtocol:
276
+ __slots__ = ("modes", "__call__")
277
+
278
+ modes: set[StreamMode]
279
+
280
+ __call__: Callable[[StreamChunk], None]
281
+
282
+ def __init__(
283
+ self,
284
+ __call__: Callable[[StreamChunk], None],
285
+ modes: set[StreamMode],
286
+ ) -> None:
287
+ self.__call__ = __call__
288
+ self.modes = modes
@@ -0,0 +1,38 @@
1
+ """Re-export types moved to coco_graph.types"""
2
+
3
+ from coco_graph.types import (
4
+ All,
5
+ CachePolicy,
6
+ PregelExecutableTask,
7
+ PregelTask,
8
+ RetryPolicy,
9
+ StateSnapshot,
10
+ StateUpdate,
11
+ StreamMode,
12
+ StreamWriter,
13
+ default_retry_on,
14
+ )
15
+
16
+ __all__ = [
17
+ "All",
18
+ "StateUpdate",
19
+ "CachePolicy",
20
+ "PregelExecutableTask",
21
+ "PregelTask",
22
+ "RetryPolicy",
23
+ "StateSnapshot",
24
+ "StreamMode",
25
+ "StreamWriter",
26
+ "default_retry_on",
27
+ ]
28
+
29
+ from warnings import warn
30
+
31
+ from coco_graph.warnings import CocoGraphDeprecatedSinceV10
32
+
33
+ warn(
34
+ "Importing from coco_graph.pregel.types is deprecated. "
35
+ "Please use 'from coco_graph.types import ...' instead.",
36
+ CocoGraphDeprecatedSinceV10,
37
+ stacklevel=2,
38
+ )
coco_graph/py.typed ADDED
File without changes
coco_graph/runtime.py ADDED
@@ -0,0 +1,350 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable, Iterator, Sequence
4
+ from dataclasses import dataclass, field, replace
5
+ from typing import Any, Generic, Protocol, cast, runtime_checkable
6
+
7
+ from coco_graph.store.base import BaseStore
8
+ from typing_extensions import TypedDict, Unpack
9
+
10
+ from coco_graph._internal._constants import CONF, CONFIG_KEY_RUNTIME
11
+ from coco_graph.config import get_config
12
+ from coco_graph.types import _DC_KWARGS, StreamWriter
13
+ from coco_graph.typing import ContextT
14
+
15
+ __all__ = (
16
+ "BaseUser",
17
+ "ExecutionInfo",
18
+ "RunControl",
19
+ "Runtime",
20
+ "ServerInfo",
21
+ "get_runtime",
22
+ )
23
+
24
+
25
+ @runtime_checkable
26
+ class BaseUser(Protocol):
27
+ """The authenticated user a server attaches to a run.
28
+
29
+ Defined here rather than imported from the upstream platform client, which
30
+ this framework does not depend on. Same shape: attributes and dict access.
31
+ """
32
+
33
+ @property
34
+ def is_authenticated(self) -> bool:
35
+ """Whether the user is authenticated."""
36
+ ...
37
+
38
+ @property
39
+ def display_name(self) -> str:
40
+ """The display name of the user."""
41
+ ...
42
+
43
+ @property
44
+ def identity(self) -> str:
45
+ """The unique identifier for the user."""
46
+ ...
47
+
48
+ @property
49
+ def permissions(self) -> Sequence[str]:
50
+ """The permissions associated with the user."""
51
+ ...
52
+
53
+ def __getitem__(self, key: str) -> Any:
54
+ """Get a key from the user."""
55
+ ...
56
+
57
+ def __contains__(self, key: object) -> bool:
58
+ """Check if a key exists on the user."""
59
+ ...
60
+
61
+ def __iter__(self) -> Iterator[str]:
62
+ """Iterate over the user's keys."""
63
+ ...
64
+
65
+
66
+ @dataclass(frozen=True, slots=True)
67
+ class ExecutionInfo:
68
+ """Read-only execution info/metadata for the execution of current thread/run/node."""
69
+
70
+ checkpoint_id: str
71
+ """The checkpoint ID for the current execution."""
72
+
73
+ checkpoint_ns: str
74
+ """The checkpoint namespace for the current execution."""
75
+
76
+ task_id: str
77
+ """The task ID for the current execution."""
78
+
79
+ thread_id: str | None = None
80
+ """The thread ID for the current execution.
81
+
82
+ None when running without a checkpointer (i.e., no persistence)."""
83
+
84
+ run_id: str | None = None
85
+ """The run ID for the current execution.
86
+
87
+ None when `run_id` is not provided in the RunnableConfig."""
88
+
89
+ node_attempt: int = 1
90
+ """Current node execution attempt number (1-indexed)."""
91
+
92
+ node_first_attempt_time: float | None = None
93
+ """Unix timestamp (seconds) for when the first attempt started."""
94
+
95
+ def patch(self, **overrides: Any) -> ExecutionInfo:
96
+ """Return a new execution info object with selected fields replaced."""
97
+ return replace(self, **overrides)
98
+
99
+
100
+ @dataclass(frozen=True, slots=True)
101
+ class ServerInfo:
102
+ """Metadata injected by CocoGraph Server. None when running open-source CocoGraph without LangSmith deployments."""
103
+
104
+ assistant_id: str
105
+ """The assistant ID for the current execution."""
106
+
107
+ graph_id: str
108
+ """The graph ID for the current execution."""
109
+
110
+ user: BaseUser | None = None
111
+ """The authenticated user, if any.
112
+
113
+ This implements the `BaseUser` protocol above,
114
+ which supports both attribute access (e.g. `user.identity`) and dict-like
115
+ access (e.g. `user["identity"]`).
116
+ """
117
+
118
+
119
+ class RunControl:
120
+ """Run-scoped control surface for cooperative draining.
121
+
122
+ Intended for a single graph run. Create a fresh `RunControl` per run;
123
+ reusing a control after `request_drain()` leaves it drained.
124
+
125
+ Safe to call from any thread: the drain request is represented by a
126
+ single attribute write, so no lock is needed for this signal.
127
+ If more mutable state is added here, add synchronization.
128
+ """
129
+
130
+ __slots__ = ("_drain_reason",)
131
+
132
+ def __init__(self) -> None:
133
+ self._drain_reason: str | None = None
134
+
135
+ def request_drain(self, reason: str = "shutdown") -> None:
136
+ self._drain_reason = reason
137
+
138
+ @property
139
+ def drain_requested(self) -> bool:
140
+ return self._drain_reason is not None
141
+
142
+ @property
143
+ def drain_reason(self) -> str | None:
144
+ return self._drain_reason
145
+
146
+
147
+ def _no_op_stream_writer(_: Any) -> None: ...
148
+
149
+
150
+ def _no_op_heartbeat() -> None: ...
151
+
152
+
153
+ class _RuntimeOverrides(TypedDict, Generic[ContextT], total=False):
154
+ context: ContextT
155
+ store: BaseStore | None
156
+ stream_writer: StreamWriter
157
+ heartbeat: Callable[[], None]
158
+ previous: Any
159
+ execution_info: ExecutionInfo
160
+ server_info: ServerInfo | None
161
+ control: RunControl | None
162
+
163
+
164
+ @dataclass(**_DC_KWARGS)
165
+ class Runtime(Generic[ContextT]):
166
+ """Convenience class that bundles run-scoped context and other runtime utilities.
167
+
168
+ This class is injected into graph nodes and middleware. It provides access to
169
+ `context`, `store`, `stream_writer`, `previous`, and `execution_info`.
170
+
171
+ !!! note "Accessing `config`"
172
+
173
+ `Runtime` does not include `config`. To access `RunnableConfig`, you can inject
174
+ it directly by adding a `config: RunnableConfig` parameter to your node function
175
+ (recommended), or use `get_config()` from `coco_graph.config`.
176
+
177
+ !!! note
178
+ `ToolRuntime` (from `coco_graph.prebuilt`) is a subclass that provides similar
179
+ functionality but is designed specifically for tools. It shares `context`, `store`,
180
+ and `stream_writer` with `Runtime`, and adds tool-specific attributes like `config`,
181
+ `state`, and `tool_call_id`.
182
+
183
+ !!! version-added "Added in version v0.6.0"
184
+
185
+ Example:
186
+
187
+ ```python
188
+ from typing import TypedDict
189
+ from coco_graph.graph import StateGraph
190
+ from dataclasses import dataclass
191
+ from coco_graph.runtime import Runtime
192
+ from coco_graph.store.memory import InMemoryStore
193
+
194
+
195
+ @dataclass
196
+ class Context: # (1)!
197
+ user_id: str
198
+
199
+
200
+ class State(TypedDict, total=False):
201
+ response: str
202
+
203
+
204
+ store = InMemoryStore() # (2)!
205
+ store.put(("users",), "user_123", {"name": "Alice"})
206
+
207
+
208
+ def personalized_greeting(state: State, runtime: Runtime[Context]) -> State:
209
+ '''Generate personalized greeting using runtime context and store.'''
210
+ user_id = runtime.context.user_id # (3)!
211
+ name = "unknown_user"
212
+ if runtime.store:
213
+ if memory := runtime.store.get(("users",), user_id):
214
+ name = memory.value["name"]
215
+
216
+ response = f"Hello {name}! Nice to see you again."
217
+ return {"response": response}
218
+
219
+
220
+ graph = (
221
+ StateGraph(state_schema=State, context_schema=Context)
222
+ .add_node("personalized_greeting", personalized_greeting)
223
+ .set_entry_point("personalized_greeting")
224
+ .set_finish_point("personalized_greeting")
225
+ .compile(store=store)
226
+ )
227
+
228
+ result = graph.invoke({}, context=Context(user_id="user_123"))
229
+ print(result)
230
+ # > {'response': 'Hello Alice! Nice to see you again.'}
231
+ ```
232
+
233
+ 1. Define a schema for the runtime context.
234
+ 2. Create a store to persist memories and other information.
235
+ 3. Use the runtime context to access the `user_id`.
236
+ """
237
+
238
+ context: ContextT = field(default=None) # type: ignore[assignment]
239
+ """Static context for the graph run, like `user_id`, `db_conn`, etc.
240
+
241
+ Can also be thought of as 'run dependencies'."""
242
+
243
+ store: BaseStore | None = field(default=None)
244
+ """Store for the graph run, enabling persistence and memory."""
245
+
246
+ stream_writer: StreamWriter = field(default=_no_op_stream_writer)
247
+ """Function that writes to the custom stream."""
248
+
249
+ heartbeat: Callable[[], None] = field(default=_no_op_heartbeat)
250
+ """Record progress for the current node's `idle_timeout`.
251
+
252
+ Call this from inside long-running work that does not naturally emit
253
+ writes, stream chunks, child tasks, or Coco callback events, to
254
+ prevent the node from being treated as idle. It is also the only
255
+ progress signal honored under `TimeoutPolicy(refresh_on="heartbeat")`.
256
+ Outside an idle-timed attempt this is a no-op.
257
+ """
258
+
259
+ previous: Any = field(default=None)
260
+ """The previous return value for the given thread.
261
+
262
+ Only available with the functional API when a checkpointer is provided.
263
+ """
264
+
265
+ execution_info: ExecutionInfo | None = field(default=None)
266
+ """Read-only execution information/metadata for the current node run.
267
+
268
+ None before task preparation populates it."""
269
+
270
+ server_info: ServerInfo | None = field(default=None)
271
+ """Metadata injected by CocoGraph Server. None when running open-source CocoGraph without LangSmith deployments."""
272
+
273
+ control: RunControl | None = field(default=None)
274
+ """Run-scoped control plane for cooperative draining.
275
+
276
+ Populated automatically during graph runs. None outside an active
277
+ graph runtime.
278
+ """
279
+
280
+ def merge(self, other: Runtime[ContextT]) -> Runtime[ContextT]:
281
+ """Merge two runtimes together.
282
+
283
+ If a value is not provided in the other runtime, the value from the current runtime is used.
284
+ """
285
+ return Runtime(
286
+ context=other.context or self.context,
287
+ store=other.store or self.store,
288
+ stream_writer=other.stream_writer
289
+ if other.stream_writer is not _no_op_stream_writer
290
+ else self.stream_writer,
291
+ heartbeat=other.heartbeat
292
+ if other.heartbeat is not _no_op_heartbeat
293
+ else self.heartbeat,
294
+ previous=self.previous if other.previous is None else other.previous,
295
+ execution_info=other.execution_info or self.execution_info,
296
+ server_info=other.server_info or self.server_info,
297
+ control=other.control or self.control,
298
+ )
299
+
300
+ def override(
301
+ self, **overrides: Unpack[_RuntimeOverrides[ContextT]]
302
+ ) -> Runtime[ContextT]:
303
+ """Replace the runtime with a new runtime with the given overrides."""
304
+ return replace(self, **overrides)
305
+
306
+ def patch_execution_info(self, **overrides: Any) -> Runtime[ContextT]:
307
+ """Return a new runtime with selected execution_info fields replaced."""
308
+ if self.execution_info is None:
309
+ msg = "Cannot patch execution_info before it has been set"
310
+ raise RuntimeError(msg)
311
+ return replace(
312
+ self,
313
+ execution_info=self.execution_info.patch(**overrides),
314
+ )
315
+
316
+ @property
317
+ def drain_requested(self) -> bool:
318
+ return self.control.drain_requested if self.control is not None else False
319
+
320
+ @property
321
+ def drain_reason(self) -> str | None:
322
+ return self.control.drain_reason if self.control is not None else None
323
+
324
+
325
+ DEFAULT_RUNTIME = Runtime(
326
+ context=None,
327
+ store=None,
328
+ stream_writer=_no_op_stream_writer,
329
+ heartbeat=_no_op_heartbeat,
330
+ previous=None,
331
+ execution_info=None,
332
+ control=None,
333
+ )
334
+
335
+
336
+ def get_runtime(context_schema: type[ContextT] | None = None) -> Runtime[ContextT]:
337
+ """Get the runtime for the current graph run.
338
+
339
+ Args:
340
+ context_schema: Optional schema used for type hinting the return type of the runtime.
341
+
342
+ Returns:
343
+ The runtime for the current graph run.
344
+ """
345
+
346
+ # TODO: in an ideal world, we would have a context manager for
347
+ # the runtime that's independent of the config. this will follow
348
+ # from the removal of the configurable packing
349
+ runtime = cast(Runtime[ContextT], get_config()[CONF].get(CONFIG_KEY_RUNTIME))
350
+ return runtime