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,620 @@
1
+ from __future__ import annotations
2
+
3
+ import functools
4
+ import inspect
5
+ import warnings
6
+ from collections.abc import Awaitable, Callable, Sequence
7
+ from dataclasses import dataclass
8
+ from datetime import timedelta
9
+ from typing import (
10
+ Any,
11
+ Generic,
12
+ TypeVar,
13
+ cast,
14
+ get_args,
15
+ get_origin,
16
+ overload,
17
+ )
18
+
19
+ from coco_graph.cache.base import BaseCache
20
+ from coco_graph.checkpoint.base import BaseCheckpointSaver
21
+ from coco_graph.store.base import BaseStore
22
+ from typing_extensions import Unpack
23
+
24
+ from coco_graph._internal import _serde
25
+ from coco_graph._internal._constants import CACHE_NS_WRITES, PREVIOUS
26
+ from coco_graph._internal._runnable import is_async_callable
27
+ from coco_graph._internal._timeout import (
28
+ coerce_timeout_policy,
29
+ sync_timeout_unsupported,
30
+ )
31
+ from coco_graph._internal._typing import MISSING, DeprecatedKwargs
32
+ from coco_graph.channels.ephemeral_value import EphemeralValue
33
+ from coco_graph.channels.last_value import LastValue
34
+ from coco_graph.constants import END, START
35
+ from coco_graph.pregel import Pregel
36
+ from coco_graph.pregel._call import (
37
+ P,
38
+ SyncAsyncFuture,
39
+ T,
40
+ _call_with_options,
41
+ get_runnable_for_entrypoint,
42
+ identifier,
43
+ )
44
+ from coco_graph.pregel._read import PregelNode
45
+ from coco_graph.pregel._write import ChannelWrite, ChannelWriteEntry
46
+ from coco_graph.types import (
47
+ _DC_KWARGS,
48
+ CachePolicy,
49
+ RetryPolicy,
50
+ StreamMode,
51
+ TimeoutPolicy,
52
+ )
53
+ from coco_graph.typing import ContextT
54
+ from coco_graph.warnings import CocoGraphDeprecatedSinceV05, CocoGraphDeprecatedSinceV10
55
+
56
+ __all__ = ("task", "entrypoint")
57
+
58
+
59
+ class _TaskFunction(Generic[P, T]):
60
+ def __init__(
61
+ self,
62
+ func: Callable[P, Awaitable[T]] | Callable[P, T],
63
+ *,
64
+ retry_policy: Sequence[RetryPolicy],
65
+ cache_policy: CachePolicy[Callable[P, str | bytes]] | None = None,
66
+ timeout: TimeoutPolicy | None = None,
67
+ name: str | None = None,
68
+ ) -> None:
69
+ if name is not None:
70
+ if hasattr(func, "__func__"):
71
+ # handle class methods
72
+ # NOTE: we're modifying the instance method to avoid modifying
73
+ # the original class method in case it's shared across multiple tasks
74
+ instance_method = functools.partial(func.__func__, func.__self__) # type: ignore [union-attr]
75
+ instance_method.__name__ = name # type: ignore [attr-defined]
76
+ func = instance_method
77
+ else:
78
+ # handle regular functions / partials / callable classes, etc.
79
+ func.__name__ = name
80
+ self.func = func
81
+ self.retry_policy = retry_policy
82
+ self.cache_policy = cache_policy
83
+ self.timeout = timeout
84
+ functools.update_wrapper(self, func)
85
+
86
+ def __call__(self, *args: P.args, **kwargs: P.kwargs) -> SyncAsyncFuture[T]:
87
+ return _call_with_options(
88
+ self.func,
89
+ args,
90
+ kwargs,
91
+ retry_policy=self.retry_policy,
92
+ cache_policy=self.cache_policy,
93
+ timeout=self.timeout,
94
+ )
95
+
96
+ def clear_cache(self, cache: BaseCache) -> None:
97
+ """Clear the cache for this task."""
98
+ if self.cache_policy is not None:
99
+ cache.clear(((CACHE_NS_WRITES, identifier(self.func) or "__dynamic__"),))
100
+
101
+ async def aclear_cache(self, cache: BaseCache) -> None:
102
+ """Clear the cache for this task."""
103
+ if self.cache_policy is not None:
104
+ await cache.aclear(
105
+ ((CACHE_NS_WRITES, identifier(self.func) or "__dynamic__"),)
106
+ )
107
+
108
+
109
+ @overload
110
+ def task(
111
+ __func_or_none__: None = None,
112
+ *,
113
+ name: str | None = None,
114
+ retry_policy: RetryPolicy | Sequence[RetryPolicy] | None = None,
115
+ cache_policy: CachePolicy[Callable[P, str | bytes]] | None = None,
116
+ timeout: float | timedelta | TimeoutPolicy | None = None,
117
+ **kwargs: Unpack[DeprecatedKwargs],
118
+ ) -> Callable[
119
+ [Callable[P, Awaitable[T]] | Callable[P, T]],
120
+ _TaskFunction[P, T],
121
+ ]: ...
122
+
123
+
124
+ @overload
125
+ def task(__func_or_none__: Callable[P, Awaitable[T]]) -> _TaskFunction[P, T]: ...
126
+
127
+
128
+ @overload
129
+ def task(__func_or_none__: Callable[P, T]) -> _TaskFunction[P, T]: ...
130
+
131
+
132
+ def task(
133
+ __func_or_none__: Callable[P, Awaitable[T]] | Callable[P, T] | None = None,
134
+ *,
135
+ name: str | None = None,
136
+ retry_policy: RetryPolicy | Sequence[RetryPolicy] | None = None,
137
+ cache_policy: CachePolicy[Callable[P, str | bytes]] | None = None,
138
+ timeout: float | timedelta | TimeoutPolicy | None = None,
139
+ **kwargs: Unpack[DeprecatedKwargs],
140
+ ) -> (
141
+ Callable[[Callable[P, Awaitable[T]] | Callable[P, T]], _TaskFunction[P, T]]
142
+ | _TaskFunction[P, T]
143
+ ):
144
+ """Define a CocoGraph task using the `task` decorator.
145
+
146
+ !!! important "Requires python 3.11 or higher for async functions"
147
+ The `task` decorator supports both sync and async functions. To use async
148
+ functions, ensure that you are using Python 3.11 or higher.
149
+
150
+ Tasks can only be called from within an [`entrypoint`][coco_graph.func.entrypoint] or
151
+ from within a `StateGraph`. A task can be called like a regular function with the
152
+ following differences:
153
+
154
+ - When a checkpointer is enabled, the function inputs and outputs must be serializable.
155
+ - The decorated function can only be called from within an entrypoint or `StateGraph`.
156
+ - Calling the function produces a future. This makes it easy to parallelize tasks.
157
+
158
+ Args:
159
+ name: An optional name for the task. If not provided, the function name will be used.
160
+ retry_policy: An optional retry policy (or list of policies) to use for the task in case of a failure.
161
+ cache_policy: An optional cache policy to use for the task. This allows caching of the task results.
162
+ timeout: Timeout for each task attempt. A number or `timedelta` is a hard
163
+ wall-clock cap and is not refreshed. Use `TimeoutPolicy` to configure
164
+ both a wall-clock `run_timeout` and an `idle_timeout` refreshed by
165
+ progress signals. For long-running work that doesn't naturally emit
166
+ progress, call `runtime.heartbeat()` from inside the task. When the
167
+ timeout fires, `NodeTimeoutError` is raised and the retry policy (if
168
+ any) decides whether to retry. Supported only for async tasks; sync
169
+ tasks cannot be safely cancelled in-process.
170
+
171
+ Returns:
172
+ A callable function when used as a decorator.
173
+
174
+ Example: Sync Task
175
+ ```python
176
+ from coco_graph.func import entrypoint, task
177
+
178
+
179
+ @task
180
+ def add_one_task(a: int) -> int:
181
+ return a + 1
182
+
183
+
184
+ @entrypoint()
185
+ def add_one(numbers: list[int]) -> list[int]:
186
+ futures = [add_one_task(n) for n in numbers]
187
+ results = [f.result() for f in futures]
188
+ return results
189
+
190
+
191
+ # Call the entrypoint
192
+ add_one.invoke([1, 2, 3]) # Returns [2, 3, 4]
193
+ ```
194
+
195
+ Example: Async Task
196
+ ```python
197
+ import asyncio
198
+ from coco_graph.func import entrypoint, task
199
+
200
+
201
+ @task
202
+ async def add_one_task(a: int) -> int:
203
+ return a + 1
204
+
205
+
206
+ @entrypoint()
207
+ async def add_one(numbers: list[int]) -> list[int]:
208
+ futures = [add_one_task(n) for n in numbers]
209
+ return asyncio.gather(*futures)
210
+
211
+
212
+ # Call the entrypoint
213
+ await add_one.ainvoke([1, 2, 3]) # Returns [2, 3, 4]
214
+ ```
215
+ """
216
+ if (retry := kwargs.get("retry", MISSING)) is not MISSING:
217
+ warnings.warn(
218
+ "`retry` is deprecated and will be removed. Please use `retry_policy` instead.",
219
+ category=CocoGraphDeprecatedSinceV05,
220
+ stacklevel=2,
221
+ )
222
+ if retry_policy is None:
223
+ retry_policy = retry # type: ignore[assignment]
224
+ timeout_policy = coerce_timeout_policy(timeout)
225
+
226
+ retry_policies: Sequence[RetryPolicy] = (
227
+ ()
228
+ if retry_policy is None
229
+ else (retry_policy,)
230
+ if isinstance(retry_policy, RetryPolicy)
231
+ else retry_policy
232
+ )
233
+
234
+ def decorator(
235
+ func: Callable[P, Awaitable[T]] | Callable[P, T],
236
+ ) -> Callable[P, SyncAsyncFuture[T]]:
237
+ if timeout_policy is not None and not is_async_callable(func):
238
+ name_ = name or getattr(func, "__name__", func.__class__.__name__)
239
+ raise sync_timeout_unsupported(str(name_), kind="Task")
240
+ return _TaskFunction(
241
+ func,
242
+ retry_policy=retry_policies,
243
+ cache_policy=cache_policy,
244
+ timeout=timeout_policy,
245
+ name=name,
246
+ )
247
+
248
+ if __func_or_none__ is not None:
249
+ return decorator(__func_or_none__)
250
+
251
+ return decorator
252
+
253
+
254
+ R = TypeVar("R")
255
+ S = TypeVar("S")
256
+
257
+
258
+ # The decorator was wrapped in a class to support the `final` attribute.
259
+ # In this form, the `final` attribute should play nicely with IDE autocompletion,
260
+ # and type checking tools.
261
+ # In addition, we'll be able to surface this information in the API Reference.
262
+ class entrypoint(Generic[ContextT]):
263
+ """Define a CocoGraph workflow using the `entrypoint` decorator.
264
+
265
+ ### Function signature
266
+
267
+ The decorated function must accept a **single parameter**, which serves as the input
268
+ to the function. This input parameter can be of any type. Use a dictionary
269
+ to pass **multiple parameters** to the function.
270
+
271
+ ### Injectable parameters
272
+
273
+ The decorated function can request access to additional parameters
274
+ that will be injected automatically at run time. These parameters include:
275
+
276
+ | Parameter | Description |
277
+ |------------------|------------------------------------------------------------------------------------------------------|
278
+ | **`config`** | A configuration object (aka `RunnableConfig`) that holds run-time configuration values. |
279
+ | **`previous`** | The previous return value for the given thread (available only when a checkpointer is provided). |
280
+ | **`runtime`** | A `Runtime` object that contains information about the current run, including context, store, writer |
281
+
282
+ The entrypoint decorator can be applied to sync functions or async functions.
283
+
284
+ ### State management
285
+
286
+ The **`previous`** parameter can be used to access the return value of the previous
287
+ invocation of the entrypoint on the same thread id. This value is only available
288
+ when a checkpointer is provided.
289
+
290
+ If you want **`previous`** to be different from the return value, you can use the
291
+ `entrypoint.final` object to return a value while saving a different value to the
292
+ checkpoint.
293
+
294
+ Args:
295
+ checkpointer: Specify a checkpointer to create a workflow that can persist
296
+ its state across runs.
297
+ store: A generalized key-value store. Some implementations may support
298
+ semantic search capabilities through an optional `index` configuration.
299
+ cache: A cache to use for caching the results of the workflow.
300
+ context_schema: Specifies the schema for the context object that will be
301
+ passed to the workflow.
302
+ cache_policy: A cache policy to use for caching the results of the workflow.
303
+ retry_policy: A retry policy (or list of policies) to use for the workflow in case of a failure.
304
+ timeout: Timeout for each workflow attempt. A number or `timedelta` is a
305
+ hard wall-clock cap and is not refreshed. Use `TimeoutPolicy` to
306
+ configure both a wall-clock `run_timeout` and an `idle_timeout`
307
+ refreshed by progress signals. For long-running work that doesn't
308
+ naturally emit progress, call `runtime.heartbeat()` from inside the
309
+ workflow. When the timeout fires, `NodeTimeoutError` is raised and
310
+ the retry policy (if any) decides whether to retry. Supported only
311
+ for async workflows; sync workflows cannot be safely cancelled
312
+ in-process.
313
+
314
+ !!! warning "`config_schema` Deprecated"
315
+ The `config_schema` parameter is deprecated in v0.6.0 and support will be removed in v2.0.0.
316
+ Please use `context_schema` instead to specify the schema for run-scoped context.
317
+
318
+
319
+ Example: Using entrypoint and tasks
320
+ ```python
321
+ import time
322
+
323
+ from coco_graph.func import entrypoint, task
324
+ from coco_graph.types import interrupt, Command
325
+ from coco_graph.checkpoint.memory import InMemorySaver
326
+
327
+ @task
328
+ def compose_essay(topic: str) -> str:
329
+ time.sleep(1.0) # Simulate slow operation
330
+ return f"An essay about {topic}"
331
+
332
+ @entrypoint(checkpointer=InMemorySaver())
333
+ def review_workflow(topic: str) -> dict:
334
+ \"\"\"Manages the workflow for generating and reviewing an essay.
335
+
336
+ The workflow includes:
337
+ 1. Generating an essay about the given topic.
338
+ 2. Interrupting the workflow for human review of the generated essay.
339
+
340
+ Upon resuming the workflow, compose_essay task will not be re-executed
341
+ as its result is cached by the checkpointer.
342
+
343
+ Args:
344
+ topic: The subject of the essay.
345
+
346
+ Returns:
347
+ dict: A dictionary containing the generated essay and the human review.
348
+ \"\"\"
349
+ essay_future = compose_essay(topic)
350
+ essay = essay_future.result()
351
+ human_review = interrupt({
352
+ \"question\": \"Please provide a review\",
353
+ \"essay\": essay
354
+ })
355
+ return {
356
+ \"essay\": essay,
357
+ \"review\": human_review,
358
+ }
359
+
360
+ # Example configuration for the workflow
361
+ config = {
362
+ \"configurable\": {
363
+ \"thread_id\": \"some_thread\"
364
+ }
365
+ }
366
+
367
+ # Topic for the essay
368
+ topic = \"cats\"
369
+
370
+ # Stream the workflow to generate the essay and await human review
371
+ for result in review_workflow.stream(topic, config):
372
+ print(result)
373
+
374
+ # Example human review provided after the interrupt
375
+ human_review = \"This essay is great.\"
376
+
377
+ # Resume the workflow with the provided human review
378
+ for result in review_workflow.stream(Command(resume=human_review), config):
379
+ print(result)
380
+ ```
381
+
382
+ Example: Accessing the previous return value
383
+ When a checkpointer is enabled the function can access the previous return value
384
+ of the previous invocation on the same thread id.
385
+
386
+ ```python
387
+ from typing import Optional
388
+
389
+ from coco_graph.checkpoint.memory import MemorySaver
390
+
391
+ from coco_graph.func import entrypoint
392
+
393
+
394
+ @entrypoint(checkpointer=InMemorySaver())
395
+ def my_workflow(input_data: str, previous: Optional[str] = None) -> str:
396
+ return "world"
397
+
398
+
399
+ config = {"configurable": {"thread_id": "some_thread"}}
400
+ my_workflow.invoke("hello", config)
401
+ ```
402
+
403
+ Example: Using `entrypoint.final` to save a value
404
+ The `entrypoint.final` object allows you to return a value while saving
405
+ a different value to the checkpoint. This value will be accessible
406
+ in the next invocation of the entrypoint via the `previous` parameter, as
407
+ long as the same thread id is used.
408
+
409
+ ```python
410
+ from typing import Any
411
+
412
+ from coco_graph.checkpoint.memory import MemorySaver
413
+
414
+ from coco_graph.func import entrypoint
415
+
416
+
417
+ @entrypoint(checkpointer=InMemorySaver())
418
+ def my_workflow(
419
+ number: int,
420
+ *,
421
+ previous: Any = None,
422
+ ) -> entrypoint.final[int, int]:
423
+ previous = previous or 0
424
+ # This will return the previous value to the caller, saving
425
+ # 2 * number to the checkpoint, which will be used in the next invocation
426
+ # for the `previous` parameter.
427
+ return entrypoint.final(value=previous, save=2 * number)
428
+
429
+
430
+ config = {"configurable": {"thread_id": "some_thread"}}
431
+
432
+ my_workflow.invoke(3, config) # 0 (previous was None)
433
+ my_workflow.invoke(1, config) # 6 (previous was 3 * 2 from the previous invocation)
434
+ ```
435
+ """
436
+
437
+ def __init__(
438
+ self,
439
+ checkpointer: BaseCheckpointSaver | None = None,
440
+ store: BaseStore | None = None,
441
+ cache: BaseCache | None = None,
442
+ context_schema: type[ContextT] | None = None,
443
+ cache_policy: CachePolicy | None = None,
444
+ retry_policy: RetryPolicy | Sequence[RetryPolicy] | None = None,
445
+ timeout: float | timedelta | TimeoutPolicy | None = None,
446
+ **kwargs: Unpack[DeprecatedKwargs],
447
+ ) -> None:
448
+ """Initialize the entrypoint decorator."""
449
+ if (config_schema := kwargs.get("config_schema", MISSING)) is not MISSING:
450
+ warnings.warn(
451
+ "`config_schema` is deprecated and will be removed. Please use `context_schema` instead.",
452
+ category=CocoGraphDeprecatedSinceV10,
453
+ stacklevel=2,
454
+ )
455
+ if context_schema is None:
456
+ context_schema = cast(type[ContextT], config_schema)
457
+
458
+ if (retry := kwargs.get("retry", MISSING)) is not MISSING:
459
+ warnings.warn(
460
+ "`retry` is deprecated and will be removed. Please use `retry_policy` instead.",
461
+ category=CocoGraphDeprecatedSinceV05,
462
+ stacklevel=2,
463
+ )
464
+ if retry_policy is None:
465
+ retry_policy = cast("RetryPolicy | Sequence[RetryPolicy]", retry)
466
+
467
+ self.checkpointer = checkpointer
468
+ self.store = store
469
+ self.cache = cache
470
+ self.cache_policy = cache_policy
471
+ self.retry_policy = retry_policy
472
+ self.timeout = coerce_timeout_policy(timeout)
473
+ self.context_schema = context_schema
474
+
475
+ @dataclass(**_DC_KWARGS)
476
+ class final(Generic[R, S]):
477
+ """A primitive that can be returned from an entrypoint.
478
+
479
+ This primitive allows to save a value to the checkpointer distinct from the
480
+ return value from the entrypoint.
481
+
482
+ Example: Decoupling the return value and the save value
483
+ ```python
484
+ from coco_graph.checkpoint.memory import InMemorySaver
485
+ from coco_graph.func import entrypoint
486
+
487
+
488
+ @entrypoint(checkpointer=InMemorySaver())
489
+ def my_workflow(
490
+ number: int,
491
+ *,
492
+ previous: Any = None,
493
+ ) -> entrypoint.final[int, int]:
494
+ previous = previous or 0
495
+ # This will return the previous value to the caller, saving
496
+ # 2 * number to the checkpoint, which will be used in the next invocation
497
+ # for the `previous` parameter.
498
+ return entrypoint.final(value=previous, save=2 * number)
499
+
500
+
501
+ config = {"configurable": {"thread_id": "1"}}
502
+
503
+ my_workflow.invoke(3, config) # 0 (previous was None)
504
+ my_workflow.invoke(1, config) # 6 (previous was 3 * 2 from the previous invocation)
505
+ ```
506
+ """
507
+
508
+ value: R
509
+ """Value to return. A value will always be returned even if it is `None`."""
510
+ save: S
511
+ """The value for the state for the next checkpoint.
512
+
513
+ A value will always be saved even if it is `None`.
514
+ """
515
+
516
+ def __call__(self, func: Callable[..., Any]) -> Pregel:
517
+ """Convert a function into a Pregel graph.
518
+
519
+ Args:
520
+ func: The function to convert. Support both sync and async functions.
521
+
522
+ Returns:
523
+ A Pregel graph.
524
+ """
525
+ # wrap generators in a function that writes to StreamWriter
526
+ if inspect.isgeneratorfunction(func) or inspect.isasyncgenfunction(func):
527
+ raise NotImplementedError(
528
+ "Generators are not supported in the Functional API."
529
+ )
530
+
531
+ bound = get_runnable_for_entrypoint(func)
532
+ stream_mode: StreamMode = "updates"
533
+
534
+ # get input and output types
535
+ sig = inspect.signature(func)
536
+ first_parameter_name = next(iter(sig.parameters.keys()), None)
537
+ if not first_parameter_name:
538
+ raise ValueError("Entrypoint function must have at least one parameter")
539
+ input_type = (
540
+ sig.parameters[first_parameter_name].annotation
541
+ if sig.parameters[first_parameter_name].annotation
542
+ is not inspect.Signature.empty
543
+ else Any
544
+ )
545
+
546
+ def _pluck_return_value(value: Any) -> Any:
547
+ """Extract the return_ value the entrypoint.final object or passthrough."""
548
+ return value.value if isinstance(value, entrypoint.final) else value
549
+
550
+ def _pluck_save_value(value: Any) -> Any:
551
+ """Get save value from the entrypoint.final object or passthrough."""
552
+ return value.save if isinstance(value, entrypoint.final) else value
553
+
554
+ output_type, save_type = Any, Any
555
+ if sig.return_annotation is not inspect.Signature.empty:
556
+ # User does not parameterize entrypoint.final properly
557
+ if (
558
+ sig.return_annotation is entrypoint.final
559
+ ): # Un-parameterized entrypoint.final
560
+ output_type = save_type = Any
561
+ else:
562
+ origin = get_origin(sig.return_annotation)
563
+ if origin is entrypoint.final:
564
+ type_annotations = get_args(sig.return_annotation)
565
+ if len(type_annotations) != 2:
566
+ raise TypeError(
567
+ "Please an annotation for both the return_ and "
568
+ "the save values."
569
+ "For example, `-> entrypoint.final[int, str]` would assign a "
570
+ "return_ a type of `int` and save the type `str`."
571
+ )
572
+ output_type, save_type = get_args(sig.return_annotation)
573
+ else:
574
+ output_type = save_type = sig.return_annotation
575
+
576
+ graph: Pregel[Any, ContextT, Any, Any] = Pregel(
577
+ nodes={
578
+ func.__name__: PregelNode(
579
+ bound=bound,
580
+ triggers=[START],
581
+ channels=START,
582
+ timeout=self.timeout,
583
+ writers=[
584
+ ChannelWrite(
585
+ [
586
+ ChannelWriteEntry(END, mapper=_pluck_return_value),
587
+ ChannelWriteEntry(PREVIOUS, mapper=_pluck_save_value),
588
+ ]
589
+ )
590
+ ],
591
+ )
592
+ },
593
+ channels={
594
+ START: EphemeralValue(input_type),
595
+ END: LastValue(output_type, END),
596
+ PREVIOUS: LastValue(save_type, PREVIOUS),
597
+ },
598
+ input_channels=START,
599
+ output_channels=END,
600
+ stream_channels=END,
601
+ stream_mode=stream_mode,
602
+ stream_eager=True,
603
+ checkpointer=self.checkpointer,
604
+ store=self.store,
605
+ cache=self.cache,
606
+ cache_policy=self.cache_policy,
607
+ retry_policy=self.retry_policy or (),
608
+ context_schema=self.context_schema,
609
+ )
610
+ if _serde.STRICT_MSGPACK_ENABLED:
611
+ serde_allowlist = _serde.build_serde_allowlist(
612
+ schemas=[input_type, output_type, save_type]
613
+ + ([self.context_schema] if self.context_schema is not None else []),
614
+ channels=graph.channels,
615
+ )
616
+ graph._serde_allowlist = serde_allowlist
617
+ graph.checkpointer = _serde.apply_checkpointer_allowlist(
618
+ graph.checkpointer, serde_allowlist
619
+ )
620
+ return graph
@@ -0,0 +1,12 @@
1
+ from coco_graph.constants import END, START
2
+ from coco_graph.graph.message import MessageGraph, MessagesState, add_messages
3
+ from coco_graph.graph.state import StateGraph
4
+
5
+ __all__ = (
6
+ "END",
7
+ "START",
8
+ "StateGraph",
9
+ "add_messages",
10
+ "MessagesState",
11
+ "MessageGraph",
12
+ )