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