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,18 @@
1
+ """Embeddings models.
2
+
3
+ !!! warning "Modules moved"
4
+
5
+ With the release of `coco 1.0.0`, several embeddings modules were moved to
6
+ `trustcoco-classic`, such as `CacheBackedEmbeddings` and all community
7
+ embeddings. See [list](https://github.com/langchain-ai/langchain/blob/bdf1cd383ce36dc18381a3bf3fb0a579337a32b5/libs/langchain/langchain/embeddings/__init__.py)
8
+ of moved modules to inform your migration.
9
+ """
10
+
11
+ from coco_core.embeddings import Embeddings
12
+
13
+ from coco.embeddings.base import init_embeddings
14
+
15
+ __all__ = [
16
+ "Embeddings",
17
+ "init_embeddings",
18
+ ]
@@ -0,0 +1,279 @@
1
+ """Factory functions for embeddings."""
2
+
3
+ import functools
4
+ import importlib
5
+ from collections.abc import Callable
6
+ from typing import Any
7
+
8
+ from coco_core.embeddings import Embeddings
9
+
10
+
11
+ def _call(cls: type[Embeddings], **kwargs: Any) -> Embeddings:
12
+ return cls(**kwargs)
13
+
14
+
15
+ _BUILTIN_PROVIDERS: dict[str, tuple[str, str, Callable[..., Embeddings]]] = {
16
+ "azure_ai": ("coco_azure_ai.embeddings", "AzureAIOpenAIApiEmbeddingsModel", _call),
17
+ "azure_openai": ("coco_openai", "AzureOpenAIEmbeddings", _call),
18
+ "bedrock": (
19
+ "coco_aws",
20
+ "BedrockEmbeddings",
21
+ lambda cls, model, **kwargs: cls(model_id=model, **kwargs),
22
+ ),
23
+ "cohere": ("coco_cohere", "CohereEmbeddings", _call),
24
+ "google_genai": ("coco_google_genai", "GoogleGenerativeAIEmbeddings", _call),
25
+ "google_vertexai": ("coco_google_vertexai", "VertexAIEmbeddings", _call),
26
+ "huggingface": (
27
+ "coco_huggingface",
28
+ "HuggingFaceEmbeddings",
29
+ lambda cls, model, **kwargs: cls(model_name=model, **kwargs),
30
+ ),
31
+ "mistralai": ("coco_mistralai", "MistralAIEmbeddings", _call),
32
+ "ollama": ("coco_ollama", "OllamaEmbeddings", _call),
33
+ "openai": ("coco_openai", "OpenAIEmbeddings", _call),
34
+ }
35
+ """Registry mapping provider names to their import configuration.
36
+
37
+ Each entry maps a provider key to a tuple of:
38
+
39
+ - `module_path`: The Python module path containing the embeddings class.
40
+ - `class_name`: The name of the embeddings class to import.
41
+ - `creator_func`: A callable that instantiates the class with provided kwargs.
42
+
43
+ !!! note
44
+
45
+ This dict is not exhaustive of all providers supported by Coco, but is
46
+ meant to cover the most popular ones and serve as a template for adding more
47
+ providers in the future. If a provider is not in this dict, it can still be
48
+ used with `init_chat_model` as long as its integration package is installed,
49
+ but the provider key will not be inferred from the model name and must be
50
+ specified explicitly via the `model_provider` parameter.
51
+
52
+ Refer to the Coco [integration documentation](https://docs.langchain.com/oss/python/integrations/providers/overview)
53
+ for a full list of supported providers and their corresponding packages.
54
+ """
55
+
56
+
57
+ @functools.lru_cache(maxsize=len(_BUILTIN_PROVIDERS))
58
+ def _get_embeddings_class_creator(provider: str) -> Callable[..., Embeddings]:
59
+ """Return a factory function that creates an embeddings model for the given provider.
60
+
61
+ This function is cached to avoid repeated module imports.
62
+
63
+ Args:
64
+ provider: The name of the model provider (e.g., `'openai'`, `'cohere'`).
65
+
66
+ Must be a key in `_BUILTIN_PROVIDERS`.
67
+
68
+ Returns:
69
+ A callable that accepts model kwargs and returns an `Embeddings` instance for
70
+ the specified provider.
71
+
72
+ Raises:
73
+ ValueError: If the provider is not in `_BUILTIN_PROVIDERS`.
74
+ ImportError: If the provider's integration package is not installed.
75
+ """
76
+ if provider not in _BUILTIN_PROVIDERS:
77
+ msg = (
78
+ f"Provider '{provider}' is not supported.\n"
79
+ f"Supported providers and their required packages:\n"
80
+ f"{_get_provider_list()}"
81
+ )
82
+ raise ValueError(msg)
83
+
84
+ module_name, class_name, creator_func = _BUILTIN_PROVIDERS[provider]
85
+ try:
86
+ module = importlib.import_module(module_name)
87
+ except ImportError as e:
88
+ top_level = module_name.split(".", maxsplit=1)[0]
89
+ pkg = top_level.replace("_", "-")
90
+ if top_level == "coco" or top_level.startswith("coco_"):
91
+ pkg = f"trust{pkg}"
92
+ msg = f"Could not import {pkg} python package. Please install it with `pip install {pkg}`"
93
+ raise ImportError(msg) from e
94
+
95
+ cls = getattr(module, class_name)
96
+ return functools.partial(creator_func, cls=cls)
97
+
98
+
99
+ def _get_provider_list() -> str:
100
+ """Get formatted list of providers and their packages."""
101
+ return "\n".join(
102
+ f" - {p}: {'trust' if pkg[0] == 'coco' or pkg[0].startswith('coco_') else ''}{pkg[0].replace('_', '-')}"
103
+ for p, pkg in _BUILTIN_PROVIDERS.items()
104
+ )
105
+
106
+
107
+ def _parse_model_string(model_name: str) -> tuple[str, str]:
108
+ """Parse a model string into provider and model name components.
109
+
110
+ The model string should be in the format 'provider:model-name', where provider
111
+ is one of the supported providers.
112
+
113
+ Args:
114
+ model_name: A model string in the format 'provider:model-name'
115
+
116
+ Returns:
117
+ A tuple of (provider, model_name)
118
+
119
+ Example:
120
+ ```python
121
+ _parse_model_string("openai:text-embedding-3-small")
122
+ # Returns: ("openai", "text-embedding-3-small")
123
+
124
+ _parse_model_string("bedrock:amazon.titan-embed-text-v1")
125
+ # Returns: ("bedrock", "amazon.titan-embed-text-v1")
126
+ ```
127
+
128
+ Raises:
129
+ ValueError: If the model string is not in the correct format or
130
+ the provider is unsupported
131
+
132
+ """
133
+ if ":" not in model_name:
134
+ msg = (
135
+ f"Invalid model format '{model_name}'.\n"
136
+ f"Model name must be in format 'provider:model-name'\n"
137
+ f"Example valid model strings:\n"
138
+ f" - openai:text-embedding-3-small\n"
139
+ f" - bedrock:amazon.titan-embed-text-v1\n"
140
+ f" - cohere:embed-english-v3.0\n"
141
+ f"Supported providers: {_BUILTIN_PROVIDERS.keys()}"
142
+ )
143
+ raise ValueError(msg)
144
+
145
+ provider, model = model_name.split(":", 1)
146
+ provider = provider.lower().strip()
147
+ model = model.strip()
148
+
149
+ if provider not in _BUILTIN_PROVIDERS:
150
+ msg = (
151
+ f"Provider '{provider}' is not supported.\n"
152
+ f"Supported providers and their required packages:\n"
153
+ f"{_get_provider_list()}"
154
+ )
155
+ raise ValueError(msg)
156
+ if not model:
157
+ msg = "Model name cannot be empty"
158
+ raise ValueError(msg)
159
+ return provider, model
160
+
161
+
162
+ def _infer_model_and_provider(
163
+ model: str,
164
+ *,
165
+ provider: str | None = None,
166
+ ) -> tuple[str, str]:
167
+ if not model.strip():
168
+ msg = "Model name cannot be empty"
169
+ raise ValueError(msg)
170
+ if provider is None and ":" in model:
171
+ provider, model_name = _parse_model_string(model)
172
+ else:
173
+ model_name = model
174
+
175
+ if not provider:
176
+ msg = (
177
+ "Must specify either:\n"
178
+ "1. A model string in format 'provider:model-name'\n"
179
+ " Example: 'openai:text-embedding-3-small'\n"
180
+ "2. Or explicitly set provider from: "
181
+ f"{_BUILTIN_PROVIDERS.keys()}"
182
+ )
183
+ raise ValueError(msg)
184
+
185
+ if provider not in _BUILTIN_PROVIDERS:
186
+ msg = (
187
+ f"Provider '{provider}' is not supported.\n"
188
+ f"Supported providers and their required packages:\n"
189
+ f"{_get_provider_list()}"
190
+ )
191
+ raise ValueError(msg)
192
+ return provider, model_name
193
+
194
+
195
+ def init_embeddings(
196
+ model: str,
197
+ *,
198
+ provider: str | None = None,
199
+ **kwargs: Any,
200
+ ) -> Embeddings:
201
+ """Initialize an embedding model from a model name and optional provider.
202
+
203
+ !!! note
204
+
205
+ Requires the integration package for the chosen model provider to be installed.
206
+
207
+ See the `model_provider` parameter below for specific package names
208
+ (e.g., `pip install trustcoco-openai`).
209
+
210
+ Refer to the [provider integration's API reference](https://docs.langchain.com/oss/python/integrations/providers)
211
+ for supported model parameters to use as `**kwargs`.
212
+
213
+ Args:
214
+ model: The name of the model, e.g. `'openai:text-embedding-3-small'`.
215
+
216
+ You can also specify model and model provider in a single argument using
217
+ `'{model_provider}:{model}'` format, e.g. `'openai:text-embedding-3-small'`.
218
+ provider: The model provider if not specified as part of the model arg
219
+ (see above).
220
+
221
+ Supported `provider` values and the corresponding integration package
222
+ are:
223
+
224
+ - `openai` -> [`trustcoco-openai`](https://docs.langchain.com/oss/python/integrations/providers/openai)
225
+ - `azure_ai` -> [`trustcoco-azure-ai`](https://docs.langchain.com/oss/python/integrations/providers/microsoft)
226
+ - `azure_openai` -> [`trustcoco-openai`](https://docs.langchain.com/oss/python/integrations/providers/openai)
227
+ - `bedrock` -> [`trustcoco-aws`](https://docs.langchain.com/oss/python/integrations/providers/aws)
228
+ - `cohere` -> [`trustcoco-cohere`](https://docs.langchain.com/oss/python/integrations/providers/cohere)
229
+ - `google_vertexai` -> [`trustcoco-google-vertexai`](https://docs.langchain.com/oss/python/integrations/providers/google)
230
+ - `huggingface` -> [`trustcoco-huggingface`](https://docs.langchain.com/oss/python/integrations/providers/huggingface)
231
+ - `mistralai` -> [`trustcoco-mistralai`](https://docs.langchain.com/oss/python/integrations/providers/mistralai)
232
+ - `ollama` -> [`trustcoco-ollama`](https://docs.langchain.com/oss/python/integrations/providers/ollama)
233
+
234
+ **kwargs: Additional model-specific parameters passed to the embedding model.
235
+
236
+ These vary by provider. Refer to the specific model provider's
237
+ [integration reference](https://reference.langchain.com/python/integrations/)
238
+ for all available parameters.
239
+
240
+ Returns:
241
+ An `Embeddings` instance that can generate embeddings for text.
242
+
243
+ Raises:
244
+ ValueError: If the model provider is not supported or cannot be determined
245
+ ImportError: If the required provider package is not installed
246
+
247
+ ???+ example
248
+
249
+ ```python
250
+ # pip install coco trustcoco-openai
251
+
252
+ # Using a model string
253
+ model = init_embeddings("openai:text-embedding-3-small")
254
+ model.embed_query("Hello, world!")
255
+
256
+ # Using explicit provider
257
+ model = init_embeddings(model="text-embedding-3-small", provider="openai")
258
+ model.embed_documents(["Hello, world!", "Goodbye, world!"])
259
+
260
+ # With additional parameters
261
+ model = init_embeddings("openai:text-embedding-3-small", api_key="sk-...")
262
+ ```
263
+
264
+ !!! version-added "Added in `coco` 0.3.9"
265
+
266
+ """
267
+ if not model:
268
+ providers = _BUILTIN_PROVIDERS.keys()
269
+ msg = f"Must specify model name. Supported providers are: {', '.join(providers)}"
270
+ raise ValueError(msg)
271
+
272
+ provider, model_name = _infer_model_and_provider(model, provider=provider)
273
+ return _get_embeddings_class_creator(provider)(model=model_name, **kwargs)
274
+
275
+
276
+ __all__ = [
277
+ "Embeddings", # This one is for backwards compatibility
278
+ "init_embeddings",
279
+ ]
coco/mcp/__init__.py ADDED
@@ -0,0 +1,36 @@
1
+ """Coco MCP adapters for connecting MCP servers with Coco applications.
2
+
3
+ Interrupt-driven elicitation has its own types — the interrupt payload, the
4
+ answers a run resumes with, and the discriminator to recognize them by. Import
5
+ those from `coco.mcp.elicitation`.
6
+
7
+ !!! warning "This namespace is in beta"
8
+
9
+ `coco.mcp` is actively being worked on and its API may change. Importing
10
+ from it raises a `CocoBetaWarning` once per process. Silence it with
11
+ `warnings.filterwarnings("ignore", category=CocoBetaWarning)`, or scope
12
+ the suppression with `coco_core._api.suppress_coco_beta_warning()`.
13
+ """
14
+
15
+ import warnings
16
+
17
+ from coco_core._api import CocoBetaWarning
18
+
19
+ from coco.mcp.adapter import MCPAdapter
20
+ from coco.mcp.tools import MCPToolArtifact, as_coco_tool
21
+
22
+ # Warned on import rather than through `@beta`, which annotates a function or
23
+ # class and so only fires once something is called. The status belongs to the
24
+ # whole namespace, and a caller should learn it when they reach for it —
25
+ # including when they import a submodule directly, which runs this module first.
26
+ warnings.warn(
27
+ "`coco.mcp` is in beta. It is actively being worked on, so the API may change.",
28
+ CocoBetaWarning,
29
+ stacklevel=2,
30
+ )
31
+
32
+ __all__ = [
33
+ "MCPAdapter",
34
+ "MCPToolArtifact",
35
+ "as_coco_tool",
36
+ ]
coco/mcp/adapter.py ADDED
@@ -0,0 +1,245 @@
1
+ """Adapt MCP tools into Coco tools suitable for `create_agent`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import TYPE_CHECKING, Any, Final, TypeAlias
7
+
8
+ from pydantic import AnyUrl, TypeAdapter, ValidationError
9
+ from typing_extensions import Self
10
+
11
+ from coco.mcp.elicitation import _arm_for_interrupts
12
+ from coco.mcp.tools import as_coco_tool
13
+
14
+ try:
15
+ from fastmcp.client import Client as FastMCPClient
16
+ from fastmcp.client.group import ClientGroup
17
+ from fastmcp.client.transports import ClientTransport
18
+ from fastmcp.mcp_config import MCPConfig
19
+ from mcp.server.mcpserver import MCPServer
20
+ except ImportError as _import_error:
21
+ msg = "Please install FastMCP to use `MCPAdapter` — `pip install fastmcp`."
22
+ raise ImportError(msg) from _import_error
23
+
24
+
25
+ if TYPE_CHECKING:
26
+ from types import TracebackType
27
+
28
+ from fastmcp import FastMCP
29
+ from coco_core.tools import BaseTool
30
+
31
+ # `CacheMode` is the MCP SDK's own type (SEP-2549); FastMCP re-imports it
32
+ # rather than defining its own, so this is the canonical source.
33
+ from mcp.client.caching import CacheMode
34
+ else:
35
+ try:
36
+ from fastmcp import FastMCP
37
+ except ImportError:
38
+ # In-process FastMCP servers, and multi-server `MCPConfig` targets, live
39
+ # in the server half of FastMCP. The `mcp` extra installs it, but a
40
+ # caller who reached this module through a client-only install
41
+ # (`fastmcp-slim[client]`) can still use every other target type — so
42
+ # the annotation degrades rather than the import failing, the same way
43
+ # FastMCP degrades it in `fastmcp.client.transports.inference`.
44
+ FastMCP = Any
45
+
46
+
47
+ MCPAdapterTarget: TypeAlias = (
48
+ FastMCPClient[Any]
49
+ | ClientGroup
50
+ | ClientTransport
51
+ | FastMCP
52
+ | MCPServer
53
+ | AnyUrl
54
+ | Path
55
+ | MCPConfig
56
+ | dict[str, Any]
57
+ | str
58
+ )
59
+ """Anything `MCPAdapter` accepts as its `target`.
60
+
61
+ Every transport `fastmcp.Client` accepts, plus a pre-built `fastmcp.Client`.
62
+
63
+ A `str` target is the one member narrowed relative to `fastmcp.Client`: it must
64
+ be an `http`/`https` URL. Local servers are reached through `Path`, an explicit
65
+ transport, or `MCPConfig` — see `MCPAdapter`.
66
+
67
+ `ClientGroup` is the one member `fastmcp.Client` does not accept at all, since a
68
+ group is a peer of `Client` rather than a transport it could wrap.
69
+ """
70
+
71
+
72
+ _URL_SCHEMES: Final = frozenset({"http", "https"})
73
+ """Schemes a `str` target may carry.
74
+
75
+ The only schemes `fastmcp.Client` can reach a server over from a string, so
76
+ nothing that would have connected is forbidden here. It selects that branch on
77
+ a bare `str.startswith("http")` though, which also admits strings that are not
78
+ URLs at all — those fail on connect there, and on construction here.
79
+ """
80
+
81
+ _ANY_URL: Final = TypeAdapter(AnyUrl)
82
+
83
+
84
+ def _validate_url_target(target: str) -> None:
85
+ """Reject a `str` target that is not an `http`/`https` URL.
86
+
87
+ `fastmcp.Client` infers a transport from a string by testing it as a
88
+ filesystem path *before* testing it as a URL, so a string naming an
89
+ existing `.py` or `.js` file launches that file as a subprocess. A string
90
+ that reaches an application from configuration, a request body, or a model
91
+ is expected to address a server over the network; letting it silently
92
+ select local execution instead makes the dangerous reading the implicit
93
+ one.
94
+
95
+ Args:
96
+ target: The string passed as the adapter's target.
97
+
98
+ Raises:
99
+ ValueError: If `target` is not an `http` or `https` URL.
100
+ """
101
+ hint = (
102
+ "To run a local MCP server over stdio, ask for it explicitly with "
103
+ "`Path('server.py')`, a `fastmcp` transport, or an `MCPConfig` — a bare "
104
+ "string is read as a URL so that it cannot silently become a subprocess."
105
+ )
106
+ try:
107
+ url = _ANY_URL.validate_python(target)
108
+ except ValidationError as validation_error:
109
+ msg = f"MCP target {target!r} is not a valid URL. {hint}"
110
+ raise ValueError(msg) from validation_error
111
+
112
+ # `AnyUrl` alone is not the boundary. It reads a Windows path such as
113
+ # `C:\server.py` as the scheme `c` and accepts it — and on Windows that
114
+ # path *does* resolve, so FastMCP would launch it. Schemes FastMCP cannot
115
+ # infer a transport from at all (`file:`, `ws:`) are refused here too, for
116
+ # an error that names the problem rather than "could not infer a transport".
117
+ if url.scheme not in _URL_SCHEMES:
118
+ msg = (
119
+ f"MCP target {target!r} has scheme {url.scheme!r}, but a string target must "
120
+ f"be an http or https URL. {hint}"
121
+ )
122
+ raise ValueError(msg)
123
+
124
+
125
+ class MCPAdapter:
126
+ """Adapt an MCP target into Coco tools.
127
+
128
+ `MCPAdapter` uses FastMCP for protocol negotiation and connection management,
129
+ then converts discovered MCP tools into asynchronous Coco tools. The
130
+ resulting tools can be passed directly to `create_agent`.
131
+
132
+ Transport inference is delegated to `fastmcp.Client`, so a target may be a URL,
133
+ a local script path (launched over stdio), an in-process server, or an already
134
+ constructed client.
135
+
136
+ !!! warning "A string target must be an http(s) URL"
137
+
138
+ `fastmcp.Client` resolves a string by testing it as a filesystem path
139
+ before testing it as a URL, so a string naming an existing `.py` or `.js`
140
+ file launches that file as a subprocess. Because strings are the form a
141
+ target most often arrives in from configuration or from a model,
142
+ `MCPAdapter` rejects one that is not an `http` or `https` URL rather than
143
+ let it select local execution. Reach a local server through `Path`, a
144
+ `fastmcp` transport, or an `MCPConfig`, all of which say so explicitly.
145
+
146
+ A server that needs input mid-call is answered with a CocoGraph
147
+ `interrupt()`, so a human answers and the run resumes — see
148
+ `coco.mcp.elicitation`. This is the default: the adapter arms every
149
+ client it builds to advertise the elicitation capability and drives the
150
+ interrupt loop on each call. A server that never asks for input is
151
+ unaffected, since the loop only runs when the server returns a request.
152
+
153
+ A pre-built client (or `ClientGroup`) that already carries its own
154
+ elicitation handler is honored rather than overridden: its handler keeps
155
+ answering, and the adapter leaves the client as the caller built it. Only a
156
+ client with no handler is armed, and it is cloned first so the caller's own
157
+ object is never mutated.
158
+
159
+ Args:
160
+ target: MCP target accepted by `fastmcp.Client`, including an existing
161
+ FastMCP client. A `str` must be an `http`/`https` URL.
162
+
163
+ Example:
164
+ ```python
165
+ from coco.agents import create_agent
166
+ from coco.mcp import MCPAdapter
167
+
168
+ async with MCPAdapter("https://example.com/mcp") as adapter:
169
+ agent = create_agent("anthropic:claude-sonnet-5", await adapter.list_tools())
170
+ result = await agent.ainvoke({"messages": [{"role": "user", "content": "..."}]})
171
+ ```
172
+ """
173
+
174
+ def __init__(self, target: MCPAdapterTarget) -> None:
175
+ """Initialize the adapter around a FastMCP target, client, or group.
176
+
177
+ Each underlying client is armed to answer elicitation with an interrupt,
178
+ unless it already carries the caller's own handler, which is honored
179
+ instead. A caller's client is cloned rather than mutated. See the class
180
+ docstring.
181
+ """
182
+
183
+ def armed(client: FastMCPClient[Any]) -> FastMCPClient[Any]:
184
+ if getattr(client, "_elicitation_callback", None) is not None:
185
+ return client
186
+ clone = client.new()
187
+ _arm_for_interrupts(clone)
188
+ return clone
189
+
190
+ if isinstance(target, ClientGroup):
191
+ members = {name: armed(client) for name, client in target.clients.items()}
192
+ self._client: FastMCPClient[Any] | ClientGroup = ClientGroup(members)
193
+ elif isinstance(target, FastMCPClient):
194
+ self._client = armed(target)
195
+ else:
196
+ if isinstance(target, str):
197
+ _validate_url_target(target)
198
+ client = FastMCPClient(target)
199
+ _arm_for_interrupts(client)
200
+ self._client = client
201
+
202
+ @property
203
+ def client(self) -> FastMCPClient[Any] | ClientGroup:
204
+ """Return the underlying FastMCP client or group for advanced MCP operations."""
205
+ return self._client
206
+
207
+ async def __aenter__(self) -> Self:
208
+ """Connect the underlying client or group for the duration of the context."""
209
+ await self._client.__aenter__()
210
+ return self
211
+
212
+ async def __aexit__(
213
+ self,
214
+ exc_type: type[BaseException] | None,
215
+ exc_value: BaseException | None,
216
+ traceback: TracebackType | None,
217
+ ) -> None:
218
+ """Release this context's hold on the underlying client or group."""
219
+ await self._client.__aexit__(exc_type, exc_value, traceback)
220
+
221
+ async def list_tools(self, *, cache_mode: CacheMode = "use") -> list[BaseTool]:
222
+ """Discover and adapt MCP tools for use with Coco.
223
+
224
+ Args:
225
+ cache_mode: How discovery interacts with the client-side response
226
+ cache (SEP-2549). `use` serves a cached tool list when one is
227
+ present and still within the server's TTL hint, `refresh` calls
228
+ the server and repopulates the cache, and `bypass` skips the
229
+ cache entirely. The cache and its per-principal isolation are
230
+ configured on the client itself (`Client(cache=...)`); this only
231
+ selects how discovery reads it. Defaults to `use` so a
232
+ configured cache is honored — note this differs from a bare
233
+ `ClientGroup.list_tools()`, whose own default is `refresh`.
234
+
235
+ Returns:
236
+ Coco tools that invoke the corresponding MCP tools
237
+ asynchronously. Each holds the adapter's client, so the tools
238
+ stay callable after this adapter's context exits.
239
+ """
240
+ async with self:
241
+ remote_tools = await self._client.list_tools(cache_mode=cache_mode)
242
+ return [await as_coco_tool(tool, self._client) for tool in remote_tools]
243
+
244
+
245
+ __all__ = ["MCPAdapter", "MCPAdapterTarget"]