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,73 @@
1
+ """Message and message content types.
2
+
3
+ Includes message types for different roles (e.g., human, AI, system), as well as types
4
+ for message content blocks (e.g., text, image, audio) and tool calls.
5
+ """
6
+
7
+ from coco_core.messages import (
8
+ AIMessage,
9
+ AIMessageChunk,
10
+ Annotation,
11
+ AnyMessage,
12
+ AudioContentBlock,
13
+ Citation,
14
+ ContentBlock,
15
+ DataContentBlock,
16
+ FileContentBlock,
17
+ HumanMessage,
18
+ ImageContentBlock,
19
+ InputTokenDetails,
20
+ InvalidToolCall,
21
+ MessageLikeRepresentation,
22
+ NonStandardAnnotation,
23
+ NonStandardContentBlock,
24
+ OutputTokenDetails,
25
+ PlainTextContentBlock,
26
+ ReasoningContentBlock,
27
+ RemoveMessage,
28
+ ServerToolCall,
29
+ ServerToolCallChunk,
30
+ ServerToolResult,
31
+ SystemMessage,
32
+ TextContentBlock,
33
+ ToolCall,
34
+ ToolCallChunk,
35
+ ToolMessage,
36
+ UsageMetadata,
37
+ VideoContentBlock,
38
+ trim_messages,
39
+ )
40
+
41
+ __all__ = [
42
+ "AIMessage",
43
+ "AIMessageChunk",
44
+ "Annotation",
45
+ "AnyMessage",
46
+ "AudioContentBlock",
47
+ "Citation",
48
+ "ContentBlock",
49
+ "DataContentBlock",
50
+ "FileContentBlock",
51
+ "HumanMessage",
52
+ "ImageContentBlock",
53
+ "InputTokenDetails",
54
+ "InvalidToolCall",
55
+ "MessageLikeRepresentation",
56
+ "NonStandardAnnotation",
57
+ "NonStandardContentBlock",
58
+ "OutputTokenDetails",
59
+ "PlainTextContentBlock",
60
+ "ReasoningContentBlock",
61
+ "RemoveMessage",
62
+ "ServerToolCall",
63
+ "ServerToolCallChunk",
64
+ "ServerToolResult",
65
+ "SystemMessage",
66
+ "TextContentBlock",
67
+ "ToolCall",
68
+ "ToolCallChunk",
69
+ "ToolMessage",
70
+ "UsageMetadata",
71
+ "VideoContentBlock",
72
+ "trim_messages",
73
+ ]
coco/py.typed ADDED
File without changes
@@ -0,0 +1,13 @@
1
+ """Base abstraction and in-memory implementation of rate limiters.
2
+
3
+ These rate limiters can be used to limit the rate of requests to an API.
4
+
5
+ The rate limiters can be used together with `BaseChatModel`.
6
+ """
7
+
8
+ from coco_core.rate_limiters import BaseRateLimiter, InMemoryRateLimiter
9
+
10
+ __all__ = [
11
+ "BaseRateLimiter",
12
+ "InMemoryRateLimiter",
13
+ ]
coco/tools/__init__.py ADDED
@@ -0,0 +1,22 @@
1
+ """Tools."""
2
+
3
+ from coco_core.tools import (
4
+ BaseTool,
5
+ InjectedToolArg,
6
+ InjectedToolCallId,
7
+ ToolException,
8
+ tool,
9
+ )
10
+
11
+ from coco.tools.tool_node import InjectedState, InjectedStore, ToolRuntime
12
+
13
+ __all__ = [
14
+ "BaseTool",
15
+ "InjectedState",
16
+ "InjectedStore",
17
+ "InjectedToolArg",
18
+ "InjectedToolCallId",
19
+ "ToolException",
20
+ "ToolRuntime",
21
+ "tool",
22
+ ]
@@ -0,0 +1,20 @@
1
+ """Utils file included for backwards compat imports."""
2
+
3
+ from coco_graph.prebuilt import InjectedState, InjectedStore, ToolRuntime
4
+ from coco_graph.prebuilt.tool_node import (
5
+ ToolCallRequest,
6
+ ToolCallWithContext,
7
+ ToolCallWrapper,
8
+ )
9
+ from coco_graph.prebuilt.tool_node import (
10
+ ToolNode as _ToolNode, # noqa: F401
11
+ )
12
+
13
+ __all__ = [
14
+ "InjectedState",
15
+ "InjectedStore",
16
+ "ToolCallRequest",
17
+ "ToolCallWithContext",
18
+ "ToolCallWrapper",
19
+ "ToolRuntime",
20
+ ]
@@ -0,0 +1,15 @@
1
+ """Claude (Anthropic) partner package for Coco."""
2
+
3
+ from coco_anthropic._version import __version__
4
+ from coco_anthropic.chat_models import (
5
+ ChatAnthropic,
6
+ convert_to_anthropic_tool,
7
+ )
8
+ from coco_anthropic.llms import AnthropicLLM
9
+
10
+ __all__ = [
11
+ "AnthropicLLM",
12
+ "ChatAnthropic",
13
+ "__version__",
14
+ "convert_to_anthropic_tool",
15
+ ]
@@ -0,0 +1,81 @@
1
+ """Helpers for creating Anthropic API clients.
2
+
3
+ This module allows for the caching of httpx clients to avoid creating new instances
4
+ for each instance of ChatAnthropic.
5
+
6
+ Logic is largely replicated from anthropic._base_client.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import asyncio
12
+ import os
13
+ from functools import lru_cache
14
+ from typing import Any
15
+
16
+ import anthropic
17
+
18
+ _NOT_GIVEN: Any = object()
19
+
20
+
21
+ class _SyncHttpxClientWrapper(anthropic.DefaultHttpxClient):
22
+ """Borrowed from anthropic._base_client."""
23
+
24
+ def __del__(self) -> None:
25
+ try:
26
+ if self.is_closed:
27
+ return
28
+ self.close()
29
+ except Exception: # noqa: S110
30
+ pass
31
+
32
+
33
+ class _AsyncHttpxClientWrapper(anthropic.DefaultAsyncHttpxClient):
34
+ """Borrowed from anthropic._base_client."""
35
+
36
+ def __del__(self) -> None:
37
+ try:
38
+ if self.is_closed:
39
+ return
40
+ # TODO(someday): support non asyncio runtimes here
41
+ asyncio.get_running_loop().create_task(self.aclose())
42
+ except Exception: # noqa: S110
43
+ pass
44
+
45
+
46
+ @lru_cache
47
+ def _get_default_httpx_client(
48
+ *,
49
+ base_url: str | None,
50
+ timeout: Any = _NOT_GIVEN,
51
+ anthropic_proxy: str | None = None,
52
+ ) -> _SyncHttpxClientWrapper:
53
+ kwargs: dict[str, Any] = {
54
+ "base_url": base_url
55
+ or os.environ.get("ANTHROPIC_BASE_URL")
56
+ or "https://api.anthropic.com",
57
+ }
58
+ if timeout is not _NOT_GIVEN:
59
+ kwargs["timeout"] = timeout
60
+ if anthropic_proxy is not None:
61
+ kwargs["proxy"] = anthropic_proxy
62
+ return _SyncHttpxClientWrapper(**kwargs)
63
+
64
+
65
+ @lru_cache
66
+ def _get_default_async_httpx_client(
67
+ *,
68
+ base_url: str | None,
69
+ timeout: Any = _NOT_GIVEN,
70
+ anthropic_proxy: str | None = None,
71
+ ) -> _AsyncHttpxClientWrapper:
72
+ kwargs: dict[str, Any] = {
73
+ "base_url": base_url
74
+ or os.environ.get("ANTHROPIC_BASE_URL")
75
+ or "https://api.anthropic.com",
76
+ }
77
+ if timeout is not _NOT_GIVEN:
78
+ kwargs["timeout"] = timeout
79
+ if anthropic_proxy is not None:
80
+ kwargs["proxy"] = anthropic_proxy
81
+ return _AsyncHttpxClientWrapper(**kwargs)
@@ -0,0 +1,228 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from typing import Any, cast
5
+
6
+ from coco_core.messages import content as types
7
+
8
+
9
+ def _unwrap_non_standard(block: dict) -> dict:
10
+ """Unwrap a provider-native dictionary from a standard content block."""
11
+ if block.get("type") == "non_standard" and isinstance(
12
+ value := block.get("value"),
13
+ dict,
14
+ ):
15
+ return value
16
+ return block
17
+
18
+
19
+ def _convert_annotation_from_v1(annotation: types.Annotation) -> dict[str, Any]:
20
+ """Convert Coco annotation format to Anthropic's native citation format."""
21
+ if annotation["type"] == "non_standard_annotation":
22
+ return annotation["value"]
23
+
24
+ if annotation["type"] == "citation":
25
+ if "url" in annotation:
26
+ # web_search_result_location
27
+ out: dict[str, Any] = {}
28
+ if cited_text := annotation.get("cited_text"):
29
+ out["cited_text"] = cited_text
30
+ if "encrypted_index" in annotation.get("extras", {}):
31
+ out["encrypted_index"] = annotation.get("extras", {})["encrypted_index"]
32
+ if "title" in annotation:
33
+ out["title"] = annotation["title"]
34
+ out["type"] = "web_search_result_location"
35
+ out["url"] = annotation.get("url")
36
+
37
+ for key, value in annotation.get("extras", {}).items():
38
+ if key not in out:
39
+ out[key] = value
40
+
41
+ return out
42
+
43
+ if "start_char_index" in annotation.get("extras", {}):
44
+ # char_location
45
+ out = {"type": "char_location"}
46
+ for field in ["cited_text"]:
47
+ if value := annotation.get(field):
48
+ out[field] = value
49
+ if title := annotation.get("title"):
50
+ out["document_title"] = title
51
+
52
+ for key, value in annotation.get("extras", {}).items():
53
+ out[key] = value
54
+ out = {k: out[k] for k in sorted(out)}
55
+
56
+ return out
57
+
58
+ if "search_result_index" in annotation.get("extras", {}):
59
+ # search_result_location
60
+ out = {"type": "search_result_location"}
61
+ for field in ["cited_text", "title"]:
62
+ if value := annotation.get(field):
63
+ out[field] = value
64
+
65
+ for key, value in annotation.get("extras", {}).items():
66
+ out[key] = value
67
+
68
+ return out
69
+
70
+ if "start_block_index" in annotation.get("extras", {}):
71
+ # content_block_location
72
+ out = {}
73
+ if cited_text := annotation.get("cited_text"):
74
+ out["cited_text"] = cited_text
75
+ if "document_index" in annotation.get("extras", {}):
76
+ out["document_index"] = annotation.get("extras", {})["document_index"]
77
+ if "title" in annotation:
78
+ out["document_title"] = annotation["title"]
79
+
80
+ for key, value in annotation.get("extras", {}).items():
81
+ if key not in out:
82
+ out[key] = value
83
+
84
+ out["type"] = "content_block_location"
85
+ return out
86
+
87
+ if "start_page_number" in annotation.get("extras", {}):
88
+ # page_location
89
+ out = {"type": "page_location"}
90
+ for field in ["cited_text"]:
91
+ if value := annotation.get(field):
92
+ out[field] = value
93
+ if title := annotation.get("title"):
94
+ out["document_title"] = title
95
+
96
+ for key, value in annotation.get("extras", {}).items():
97
+ out[key] = value
98
+
99
+ return out
100
+
101
+ return cast(dict[str, Any], annotation)
102
+
103
+ return cast(dict[str, Any], annotation)
104
+
105
+
106
+ def _convert_from_v1_to_anthropic(
107
+ content: list[types.ContentBlock],
108
+ tool_calls: list[types.ToolCall],
109
+ model_provider: str | None,
110
+ ) -> list[dict[str, Any]]:
111
+ new_content: list = []
112
+ for block in content:
113
+ if block["type"] == "text":
114
+ if model_provider == "anthropic" and "annotations" in block:
115
+ new_block: dict[str, Any] = {"type": "text"}
116
+ new_block["citations"] = [
117
+ _convert_annotation_from_v1(a) for a in block["annotations"]
118
+ ]
119
+ if "text" in block:
120
+ new_block["text"] = block["text"]
121
+ else:
122
+ new_block = {"text": block.get("text", ""), "type": "text"}
123
+ new_content.append(new_block)
124
+
125
+ elif block["type"] == "tool_call":
126
+ tool_use_block = {
127
+ "type": "tool_use",
128
+ "name": block.get("name", ""),
129
+ "input": block.get("args", {}),
130
+ "id": block.get("id", ""),
131
+ }
132
+ if "caller" in block.get("extras", {}):
133
+ tool_use_block["caller"] = block["extras"]["caller"]
134
+ new_content.append(tool_use_block)
135
+
136
+ elif block["type"] == "tool_call_chunk":
137
+ if isinstance(block["args"], str):
138
+ try:
139
+ input_ = json.loads(block["args"] or "{}")
140
+ except json.JSONDecodeError:
141
+ input_ = {}
142
+ else:
143
+ input_ = block.get("args") or {}
144
+ new_content.append(
145
+ {
146
+ "type": "tool_use",
147
+ "name": block.get("name", ""),
148
+ "input": input_,
149
+ "id": block.get("id", ""),
150
+ }
151
+ )
152
+
153
+ elif block["type"] == "invalid_tool_call":
154
+ tool_call_id = block.get("id")
155
+ tool_name = block.get("name")
156
+ if (
157
+ model_provider == "anthropic"
158
+ and isinstance(tool_call_id, str)
159
+ and tool_call_id
160
+ and isinstance(tool_name, str)
161
+ and tool_name
162
+ ):
163
+ new_content.append(
164
+ {
165
+ "type": "tool_use",
166
+ "name": tool_name,
167
+ "input": {},
168
+ "id": tool_call_id,
169
+ }
170
+ )
171
+
172
+ elif block["type"] == "reasoning" and model_provider == "anthropic":
173
+ new_block = {}
174
+ if "reasoning" in block:
175
+ new_block["thinking"] = block["reasoning"]
176
+ new_block["type"] = "thinking"
177
+ if signature := block.get("extras", {}).get("signature"):
178
+ new_block["signature"] = signature
179
+
180
+ new_content.append(new_block)
181
+
182
+ elif block["type"] == "server_tool_call" and model_provider == "anthropic":
183
+ new_block = {}
184
+ if "id" in block:
185
+ new_block["id"] = block["id"]
186
+ new_block["input"] = block.get("args", {})
187
+ if partial_json := block.get("extras", {}).get("partial_json"):
188
+ new_block["input"] = {}
189
+ new_block["partial_json"] = partial_json
190
+ else:
191
+ pass
192
+ if block.get("name") == "code_interpreter":
193
+ new_block["name"] = "code_execution"
194
+ elif block.get("name") == "remote_mcp":
195
+ if "tool_name" in block.get("extras", {}):
196
+ new_block["name"] = block["extras"]["tool_name"]
197
+ if "server_name" in block.get("extras", {}):
198
+ new_block["server_name"] = block["extras"]["server_name"]
199
+ else:
200
+ new_block["name"] = block.get("name", "")
201
+ if block.get("name") == "remote_mcp":
202
+ new_block["type"] = "mcp_tool_use"
203
+ else:
204
+ new_block["type"] = "server_tool_use"
205
+ new_content.append(new_block)
206
+
207
+ elif block["type"] == "server_tool_result" and model_provider == "anthropic":
208
+ new_block = {}
209
+ if "output" in block:
210
+ new_block["content"] = block["output"]
211
+ server_tool_result_type = block.get("extras", {}).get("block_type", "")
212
+ if server_tool_result_type == "mcp_tool_result":
213
+ new_block["is_error"] = block.get("status") == "error"
214
+ if "tool_call_id" in block:
215
+ new_block["tool_use_id"] = block["tool_call_id"]
216
+ new_block["type"] = server_tool_result_type
217
+ new_content.append(new_block)
218
+
219
+ elif (
220
+ block["type"] == "non_standard"
221
+ and "value" in block
222
+ and model_provider == "anthropic"
223
+ ):
224
+ new_content.append(block["value"])
225
+ else:
226
+ new_content.append(block)
227
+
228
+ return new_content
@@ -0,0 +1,124 @@
1
+ """Adapt to the installed `anthropic` SDK major version.
2
+
3
+ `trustcoco-anthropic` supports `anthropic` 0.x and 1.x. Two differences between
4
+ them reach this package, and each is resolved here by reading the answer off the
5
+ installed SDK rather than off its version string:
6
+
7
+ - **Sampling parameters.** `anthropic>=1` dropped `temperature`, `top_p` and
8
+ `top_k` from its message-creation methods, since current models do not use
9
+ them. The API still honors them for older models, so they are relocated to
10
+ `extra_body`, which the SDK merges into the request JSON as-is. The wire
11
+ payload is identical on both majors.
12
+
13
+ - **Raw responses.** `.with_raw_response` on the async client returns
14
+ `AsyncAPIResponse`, whose `parse()` is a coroutine; `anthropic<1` returned
15
+ `LegacyAPIResponse` with a synchronous `parse()`.
16
+
17
+ `anthropic>=1` also moved its HTTP layer from `httpx` to
18
+ [`httpx2`](https://github.com/pydantic/httpx2), but that does not surface here:
19
+ this package hands the SDK only primitives (a `base_url` string, a float
20
+ `timeout`, a `proxy` URL string) and subclasses `anthropic.DefaultHttpxClient`,
21
+ which already points at the right library, so no `httpx` type crosses the
22
+ boundary. Only the unit tests inject `httpx` objects, and they resolve the
23
+ matching library themselves in `tests/unit_tests/_httpx_compat.py`.
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import inspect
29
+ import logging
30
+ import re
31
+ from collections.abc import Mapping
32
+ from functools import lru_cache
33
+ from typing import Any
34
+
35
+ import anthropic
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+ # Sampling parameters `anthropic>=1` no longer accepts as named arguments.
40
+ _SAMPLING_PARAMS = ("temperature", "top_p", "top_k")
41
+
42
+
43
+ def _sdk_major_version() -> int | None:
44
+ """Major version of the installed `anthropic` SDK, or `None` if unreadable.
45
+
46
+ Tolerates tag-derived strings such as `v1.0.0`, which build tooling
47
+ sometimes leaves unstripped, by reading the first integer run.
48
+ """
49
+ match = re.match(r"\D*(\d+)", str(getattr(anthropic, "__version__", "")))
50
+ return int(match.group(1)) if match else None
51
+
52
+
53
+ @lru_cache(maxsize=1)
54
+ def _unsupported_sampling_params() -> frozenset[str]:
55
+ """Sampling parameters the installed SDK's message methods no longer accept.
56
+
57
+ Derived from the signature of `Messages.create`, which `beta.messages` and
58
+ the async resources track. No client is instantiated, so this is safe to
59
+ call during payload construction without resolved credentials.
60
+ """
61
+ try:
62
+ from anthropic.resources.messages import Messages
63
+
64
+ accepted = inspect.signature(Messages.create).parameters
65
+ except (ImportError, AttributeError, TypeError, ValueError):
66
+ # The SDK moved the resource or the signature is unreadable. Guess from
67
+ # the major version rather than failing: a wrong guess costs a TypeError
68
+ # on the first request, an exception here breaks every import.
69
+ major = _sdk_major_version()
70
+ logger.warning(
71
+ "Could not introspect the anthropic SDK's `Messages.create` "
72
+ "signature; falling back to its major version (%r) to decide "
73
+ "whether `temperature`/`top_p`/`top_k` are still accepted.",
74
+ major,
75
+ )
76
+ if major is not None and major >= 1:
77
+ return frozenset(_SAMPLING_PARAMS)
78
+ return frozenset()
79
+
80
+ return frozenset(p for p in _SAMPLING_PARAMS if p not in accepted)
81
+
82
+
83
+ def _route_unsupported_sampling_params(payload: dict[str, Any]) -> dict[str, Any]:
84
+ """Move sampling params the installed SDK rejects into `extra_body`.
85
+
86
+ A no-op on `anthropic<1`, where the message methods still accept them as
87
+ named arguments. Values the caller already set in `extra_body` win, since
88
+ that is the SDK's documented escape hatch and a deliberate choice.
89
+
90
+ Args:
91
+ payload: Request payload, modified in place.
92
+
93
+ Returns:
94
+ The same payload.
95
+ """
96
+ unsupported = _unsupported_sampling_params()
97
+ if not unsupported:
98
+ return payload
99
+
100
+ extra_body = payload.get("extra_body")
101
+ if extra_body is not None and not isinstance(extra_body, Mapping):
102
+ # A value the SDK would reject anyway. Leave the payload untouched
103
+ # rather than relocating params into something that cannot hold them.
104
+ return payload
105
+
106
+ relocated = {k: payload.pop(k) for k in unsupported if k in payload}
107
+ if not relocated:
108
+ return payload
109
+
110
+ payload["extra_body"] = {**relocated, **(extra_body or {})}
111
+ return payload
112
+
113
+
114
+ async def _aparse(raw_response: Any) -> Any:
115
+ """Parse a raw SDK response from the async client.
116
+
117
+ `anthropic>=1` returns `AsyncAPIResponse`, whose `parse()` is a coroutine;
118
+ `anthropic<1` returned `LegacyAPIResponse`, whose `parse()` was
119
+ synchronous.
120
+ """
121
+ parsed = raw_response.parse()
122
+ if inspect.isawaitable(parsed):
123
+ return await parsed
124
+ return parsed
@@ -0,0 +1,3 @@
1
+ """Version information for `trustcoco-anthropic`."""
2
+
3
+ __version__ = "1.7.4"