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
coco_anthropic/llms.py ADDED
@@ -0,0 +1,428 @@
1
+ """Anthropic LLM wrapper. Chat models are in `chat_models.py`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from collections.abc import AsyncIterator, Callable, Iterator, Mapping
7
+ from typing import Any
8
+
9
+ import anthropic
10
+ from coco_core._api.deprecation import deprecated
11
+ from coco_core.callbacks import (
12
+ AsyncCallbackManagerForLLMRun,
13
+ CallbackManagerForLLMRun,
14
+ )
15
+ from coco_core.language_models import BaseLanguageModel, LangSmithParams
16
+ from coco_core.language_models.llms import LLM
17
+ from coco_core.outputs import GenerationChunk
18
+ from coco_core.prompt_values import PromptValue
19
+ from coco_core.utils import get_pydantic_field_names
20
+ from coco_core.utils.utils import _build_model_kwargs, from_env, secret_from_env
21
+ from pydantic import ConfigDict, Field, SecretStr, model_validator
22
+ from typing_extensions import Self
23
+
24
+ from coco_anthropic._sdk_compat import _route_unsupported_sampling_params
25
+
26
+
27
+ class _AnthropicCommon(BaseLanguageModel):
28
+ client: Any = None
29
+
30
+ async_client: Any = None
31
+
32
+ model: str = Field(default="claude-sonnet-4-5", alias="model_name")
33
+ """Model name to use."""
34
+
35
+ max_tokens: int = Field(default=1024, alias="max_tokens_to_sample")
36
+ """Denotes the number of tokens to predict per generation."""
37
+
38
+ temperature: float | None = None
39
+ """A non-negative float that tunes the degree of randomness in generation."""
40
+
41
+ top_k: int | None = None
42
+ """Number of most likely tokens to consider at each step."""
43
+
44
+ top_p: float | None = None
45
+ """Total probability mass of tokens to consider at each step."""
46
+
47
+ streaming: bool = False
48
+ """Whether to stream the results."""
49
+
50
+ default_request_timeout: float | None = None
51
+ """Timeout for requests to Anthropic Completion API. Default is 600 seconds."""
52
+
53
+ max_retries: int = 2
54
+ """Number of retries allowed for requests sent to the Anthropic Completion API."""
55
+
56
+ anthropic_api_url: str | None = Field(
57
+ alias="base_url",
58
+ default_factory=from_env(
59
+ "ANTHROPIC_API_URL",
60
+ default="https://api.anthropic.com",
61
+ ),
62
+ )
63
+ """Base URL for API requests. Only specify if using a proxy or service emulator.
64
+
65
+ If a value isn't passed in, will attempt to read the value from
66
+ `ANTHROPIC_API_URL`. If not set, the default value `https://api.anthropic.com`
67
+ will be used.
68
+ """
69
+
70
+ anthropic_api_key: SecretStr = Field(
71
+ alias="api_key",
72
+ default_factory=secret_from_env("ANTHROPIC_API_KEY", default=""),
73
+ )
74
+ """Automatically read from env var `ANTHROPIC_API_KEY` if not provided."""
75
+
76
+ HUMAN_PROMPT: str | None = None
77
+
78
+ AI_PROMPT: str | None = None
79
+
80
+ count_tokens: Callable[[str], int] | None = None
81
+
82
+ model_kwargs: dict[str, Any] = Field(default_factory=dict)
83
+
84
+ @model_validator(mode="before")
85
+ @classmethod
86
+ def build_extra(cls, values: dict) -> Any:
87
+ all_required_field_names = get_pydantic_field_names(cls)
88
+ return _build_model_kwargs(values, all_required_field_names)
89
+
90
+ @model_validator(mode="after")
91
+ def validate_environment(self) -> Self:
92
+ """Validate that api key and python package exists in environment."""
93
+ self.client = anthropic.Anthropic(
94
+ base_url=self.anthropic_api_url,
95
+ api_key=self.anthropic_api_key.get_secret_value(),
96
+ timeout=self.default_request_timeout,
97
+ max_retries=self.max_retries,
98
+ )
99
+ self.async_client = anthropic.AsyncAnthropic(
100
+ base_url=self.anthropic_api_url,
101
+ api_key=self.anthropic_api_key.get_secret_value(),
102
+ timeout=self.default_request_timeout,
103
+ max_retries=self.max_retries,
104
+ )
105
+ # Keep for backward compatibility but not used in Messages API
106
+ self.HUMAN_PROMPT = getattr(anthropic, "HUMAN_PROMPT", None)
107
+ self.AI_PROMPT = getattr(anthropic, "AI_PROMPT", None)
108
+ return self
109
+
110
+ @property
111
+ def _default_params(self) -> Mapping[str, Any]:
112
+ """Get the default parameters for calling Anthropic API."""
113
+ d = {
114
+ "max_tokens": self.max_tokens,
115
+ "model": self.model,
116
+ }
117
+ if self.temperature is not None:
118
+ d["temperature"] = self.temperature
119
+ if self.top_k is not None:
120
+ d["top_k"] = self.top_k
121
+ if self.top_p is not None:
122
+ d["top_p"] = self.top_p
123
+ return {**d, **self.model_kwargs}
124
+
125
+ @property
126
+ def _identifying_params(self) -> Mapping[str, Any]:
127
+ """Get the identifying parameters."""
128
+ return {**self._default_params}
129
+
130
+ def _get_anthropic_stop(self, stop: list[str] | None = None) -> list[str]:
131
+ if stop is None:
132
+ stop = []
133
+ return stop
134
+
135
+
136
+ @deprecated(since="0.1.0", removal="2.0.0", alternative="ChatAnthropic")
137
+ class AnthropicLLM(LLM, _AnthropicCommon):
138
+ """Anthropic text completion large language model (legacy LLM).
139
+
140
+ To use, you should have the environment variable `ANTHROPIC_API_KEY`
141
+ set with your API key, or pass it as a named parameter to the constructor.
142
+
143
+ Example:
144
+ ```python
145
+ from coco_anthropic import AnthropicLLM
146
+
147
+ model = AnthropicLLM(model="claude-sonnet-4-5")
148
+ ```
149
+ """
150
+
151
+ model_config = ConfigDict(
152
+ populate_by_name=True,
153
+ arbitrary_types_allowed=True,
154
+ )
155
+
156
+ @property
157
+ def _llm_type(self) -> str:
158
+ """Return type of llm."""
159
+ return "anthropic-llm"
160
+
161
+ @property
162
+ def lc_secrets(self) -> dict[str, str]:
163
+ """Return a mapping of secret keys to environment variables."""
164
+ return {"anthropic_api_key": "ANTHROPIC_API_KEY"}
165
+
166
+ @classmethod
167
+ def is_lc_serializable(cls) -> bool:
168
+ """Whether this class can be serialized by coco."""
169
+ return True
170
+
171
+ @property
172
+ def _identifying_params(self) -> dict[str, Any]:
173
+ """Get the identifying parameters."""
174
+ return {
175
+ "model": self.model,
176
+ "max_tokens": self.max_tokens,
177
+ "temperature": self.temperature,
178
+ "top_k": self.top_k,
179
+ "top_p": self.top_p,
180
+ "model_kwargs": self.model_kwargs,
181
+ "streaming": self.streaming,
182
+ "default_request_timeout": self.default_request_timeout,
183
+ "max_retries": self.max_retries,
184
+ }
185
+
186
+ def _get_ls_params(
187
+ self,
188
+ stop: list[str] | None = None,
189
+ **kwargs: Any,
190
+ ) -> LangSmithParams:
191
+ """Get standard params for tracing."""
192
+ params = super()._get_ls_params(stop=stop, **kwargs)
193
+ identifying_params = self._identifying_params
194
+ if max_tokens := kwargs.get(
195
+ "max_tokens",
196
+ identifying_params.get("max_tokens"),
197
+ ):
198
+ params["ls_max_tokens"] = max_tokens
199
+ return params
200
+
201
+ def _format_messages(self, prompt: str) -> list[dict[str, str]]:
202
+ """Convert prompt to Messages API format."""
203
+ messages = []
204
+
205
+ # Handle legacy prompts that might have HUMAN_PROMPT/AI_PROMPT markers
206
+ if self.HUMAN_PROMPT and self.HUMAN_PROMPT in prompt:
207
+ # Split on human/assistant turns
208
+ parts = prompt.split(self.HUMAN_PROMPT)
209
+
210
+ for _, part in enumerate(parts):
211
+ if not part.strip():
212
+ continue
213
+
214
+ if self.AI_PROMPT and self.AI_PROMPT in part:
215
+ # Split human and assistant parts
216
+ human_part, assistant_part = part.split(self.AI_PROMPT, 1)
217
+ if human_part.strip():
218
+ messages.append({"role": "user", "content": human_part.strip()})
219
+ if assistant_part.strip():
220
+ messages.append(
221
+ {"role": "assistant", "content": assistant_part.strip()}
222
+ )
223
+ # Just human content
224
+ elif part.strip():
225
+ messages.append({"role": "user", "content": part.strip()})
226
+ else:
227
+ # Handle modern format or plain text
228
+ # Clean prompt for Messages API
229
+ content = re.sub(r"^\n*Human:\s*", "", prompt)
230
+ content = re.sub(r"\n*Assistant:\s*.*$", "", content)
231
+ if content.strip():
232
+ messages.append({"role": "user", "content": content.strip()})
233
+
234
+ # Ensure we have at least one message
235
+ if not messages:
236
+ messages = [{"role": "user", "content": prompt.strip() or "Hello"}]
237
+
238
+ return messages
239
+
240
+ def _call(
241
+ self,
242
+ prompt: str,
243
+ stop: list[str] | None = None,
244
+ run_manager: CallbackManagerForLLMRun | None = None,
245
+ **kwargs: Any,
246
+ ) -> str:
247
+ r"""Call out to Anthropic's completion endpoint.
248
+
249
+ Args:
250
+ prompt: The prompt to pass into the model.
251
+ stop: Optional list of stop words to use when generating.
252
+ run_manager: Optional callback manager for LLM run.
253
+ kwargs: Additional keyword arguments to pass to the model.
254
+
255
+ Returns:
256
+ The string generated by the model.
257
+
258
+ Example:
259
+ ```python
260
+ prompt = "What are the biggest risks facing humanity?"
261
+ prompt = f"\n\nHuman: {prompt}\n\nAssistant:"
262
+ response = model.invoke(prompt)
263
+ ```
264
+ """
265
+ if self.streaming:
266
+ completion = ""
267
+ for chunk in self._stream(
268
+ prompt=prompt,
269
+ stop=stop,
270
+ run_manager=run_manager,
271
+ **kwargs,
272
+ ):
273
+ completion += chunk.text
274
+ return completion
275
+
276
+ stop = self._get_anthropic_stop(stop)
277
+ params = {**self._default_params, **kwargs}
278
+
279
+ # Remove parameters not supported by Messages API
280
+ params = {k: v for k, v in params.items() if k != "max_tokens_to_sample"}
281
+ params = _route_unsupported_sampling_params(params)
282
+
283
+ response = self.client.messages.create(
284
+ messages=self._format_messages(prompt),
285
+ stop_sequences=stop if stop else None,
286
+ **params,
287
+ )
288
+ return response.content[0].text
289
+
290
+ def convert_prompt(self, prompt: PromptValue) -> str:
291
+ """Convert a `PromptValue` to a string."""
292
+ return prompt.to_string()
293
+
294
+ async def _acall(
295
+ self,
296
+ prompt: str,
297
+ stop: list[str] | None = None,
298
+ run_manager: AsyncCallbackManagerForLLMRun | None = None,
299
+ **kwargs: Any,
300
+ ) -> str:
301
+ """Call out to Anthropic's completion endpoint asynchronously."""
302
+ if self.streaming:
303
+ completion = ""
304
+ async for chunk in self._astream(
305
+ prompt=prompt,
306
+ stop=stop,
307
+ run_manager=run_manager,
308
+ **kwargs,
309
+ ):
310
+ completion += chunk.text
311
+ return completion
312
+
313
+ stop = self._get_anthropic_stop(stop)
314
+ params = {**self._default_params, **kwargs}
315
+
316
+ # Remove parameters not supported by Messages API
317
+ params = {k: v for k, v in params.items() if k != "max_tokens_to_sample"}
318
+ params = _route_unsupported_sampling_params(params)
319
+
320
+ response = await self.async_client.messages.create(
321
+ messages=self._format_messages(prompt),
322
+ stop_sequences=stop if stop else None,
323
+ **params,
324
+ )
325
+ return response.content[0].text
326
+
327
+ def _stream(
328
+ self,
329
+ prompt: str,
330
+ stop: list[str] | None = None,
331
+ run_manager: CallbackManagerForLLMRun | None = None,
332
+ **kwargs: Any,
333
+ ) -> Iterator[GenerationChunk]:
334
+ r"""Call Anthropic completion_stream and return the resulting generator.
335
+
336
+ Args:
337
+ prompt: The prompt to pass into the model.
338
+ stop: Optional list of stop words to use when generating.
339
+ run_manager: Optional callback manager for LLM run.
340
+ kwargs: Additional keyword arguments to pass to the model.
341
+
342
+ Returns:
343
+ A generator representing the stream of tokens from Anthropic.
344
+
345
+ Example:
346
+ ```python
347
+ prompt = "Write a poem about a stream."
348
+ prompt = f"\n\nHuman: {prompt}\n\nAssistant:"
349
+ generator = anthropic.stream(prompt)
350
+ for token in generator:
351
+ yield token
352
+ ```
353
+ """
354
+ stop = self._get_anthropic_stop(stop)
355
+ params = {**self._default_params, **kwargs}
356
+
357
+ # Remove parameters not supported by Messages API
358
+ params = {k: v for k, v in params.items() if k != "max_tokens_to_sample"}
359
+ params = _route_unsupported_sampling_params(params)
360
+
361
+ with self.client.messages.stream(
362
+ messages=self._format_messages(prompt),
363
+ stop_sequences=stop if stop else None,
364
+ **params,
365
+ ) as stream:
366
+ for event in stream:
367
+ if event.type == "content_block_delta" and hasattr(event.delta, "text"):
368
+ chunk = GenerationChunk(text=event.delta.text)
369
+ if run_manager:
370
+ run_manager.on_llm_new_token(chunk.text, chunk=chunk)
371
+ yield chunk
372
+
373
+ async def _astream(
374
+ self,
375
+ prompt: str,
376
+ stop: list[str] | None = None,
377
+ run_manager: AsyncCallbackManagerForLLMRun | None = None,
378
+ **kwargs: Any,
379
+ ) -> AsyncIterator[GenerationChunk]:
380
+ r"""Call Anthropic completion_stream and return the resulting generator.
381
+
382
+ Args:
383
+ prompt: The prompt to pass into the model.
384
+ stop: Optional list of stop words to use when generating.
385
+ run_manager: Optional callback manager for LLM run.
386
+ kwargs: Additional keyword arguments to pass to the model.
387
+
388
+ Returns:
389
+ A generator representing the stream of tokens from Anthropic.
390
+
391
+ Example:
392
+ ```python
393
+ prompt = "Write a poem about a stream."
394
+ prompt = f"\n\nHuman: {prompt}\n\nAssistant:"
395
+ generator = anthropic.stream(prompt)
396
+ for token in generator:
397
+ yield token
398
+ ```
399
+ """
400
+ stop = self._get_anthropic_stop(stop)
401
+ params = {**self._default_params, **kwargs}
402
+
403
+ # Remove parameters not supported by Messages API
404
+ params = {k: v for k, v in params.items() if k != "max_tokens_to_sample"}
405
+ params = _route_unsupported_sampling_params(params)
406
+
407
+ async with self.async_client.messages.stream(
408
+ messages=self._format_messages(prompt),
409
+ stop_sequences=stop if stop else None,
410
+ **params,
411
+ ) as stream:
412
+ async for event in stream:
413
+ if event.type == "content_block_delta" and hasattr(event.delta, "text"):
414
+ chunk = GenerationChunk(text=event.delta.text)
415
+ if run_manager:
416
+ await run_manager.on_llm_new_token(chunk.text, chunk=chunk)
417
+ yield chunk
418
+
419
+ def get_num_tokens(self, text: str) -> int:
420
+ """Calculate number of tokens."""
421
+ msg = (
422
+ "Anthropic's legacy count_tokens method was removed in anthropic 0.39.0 "
423
+ "and trustcoco-anthropic 0.3.0. Please use "
424
+ "ChatAnthropic.get_num_tokens_from_messages instead."
425
+ )
426
+ raise NotImplementedError(
427
+ msg,
428
+ )
@@ -0,0 +1,25 @@
1
+ """Middleware for Anthropic models."""
2
+
3
+ from coco_anthropic.middleware.anthropic_tools import (
4
+ FilesystemClaudeMemoryMiddleware,
5
+ FilesystemClaudeTextEditorMiddleware,
6
+ StateClaudeMemoryMiddleware,
7
+ StateClaudeTextEditorMiddleware,
8
+ )
9
+ from coco_anthropic.middleware.bash import ClaudeBashToolMiddleware
10
+ from coco_anthropic.middleware.file_search import (
11
+ StateFileSearchMiddleware,
12
+ )
13
+ from coco_anthropic.middleware.prompt_caching import (
14
+ AnthropicPromptCachingMiddleware,
15
+ )
16
+
17
+ __all__ = [
18
+ "AnthropicPromptCachingMiddleware",
19
+ "ClaudeBashToolMiddleware",
20
+ "FilesystemClaudeMemoryMiddleware",
21
+ "FilesystemClaudeTextEditorMiddleware",
22
+ "StateClaudeMemoryMiddleware",
23
+ "StateClaudeTextEditorMiddleware",
24
+ "StateFileSearchMiddleware",
25
+ ]