genkit 0.6.0__tar.gz → 0.7.0__tar.gz

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 (113) hide show
  1. {genkit-0.6.0 → genkit-0.7.0}/PKG-INFO +1 -1
  2. {genkit-0.6.0 → genkit-0.7.0}/pyproject.toml +1 -1
  3. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/__init__.py +8 -2
  4. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_aio.py +83 -26
  5. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_generate.py +650 -241
  6. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_model.py +0 -1
  7. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_prompt.py +239 -88
  8. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_testing.py +7 -1
  9. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_tools.py +1 -1
  10. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_action.py +18 -0
  11. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_error.py +7 -1
  12. genkit-0.7.0/src/genkit/_core/_middleware.py +416 -0
  13. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_model.py +1 -8
  14. genkit-0.7.0/src/genkit/_core/_plugin.py +126 -0
  15. genkit-0.7.0/src/genkit/_core/_protocols.py +69 -0
  16. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_reflection.py +27 -3
  17. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_reflection_v2.py +6 -3
  18. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_registry.py +3 -2
  19. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_typing.py +1 -0
  20. genkit-0.7.0/src/genkit/middleware/__init__.py +84 -0
  21. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/plugin_api/__init__.py +4 -1
  22. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/ai_plugin_test.py +35 -0
  23. genkit-0.7.0/tests/genkit/ai/generate_test.py +2069 -0
  24. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/prompt_test.py +185 -10
  25. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/endpoints/reflection_test.py +107 -0
  26. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/error_test.py +10 -0
  27. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/reflection_v2_test.py +131 -1
  28. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/registry_test.py +8 -0
  29. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/veneer/veneer_test.py +151 -68
  30. genkit-0.6.0/src/genkit/_ai/_middleware.py +0 -100
  31. genkit-0.6.0/src/genkit/_core/_plugin.py +0 -58
  32. genkit-0.6.0/tests/genkit/ai/generate_test.py +0 -676
  33. genkit-0.6.0/tests/genkit/ai/middleware_test.py +0 -177
  34. {genkit-0.6.0 → genkit-0.7.0}/.gitignore +0 -0
  35. {genkit-0.6.0 → genkit-0.7.0}/LICENSE +0 -0
  36. {genkit-0.6.0 → genkit-0.7.0}/README.md +0 -0
  37. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_decorators.py +0 -0
  38. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_embedding.py +0 -0
  39. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_evaluator.py +0 -0
  40. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_formats/__init__.py +0 -0
  41. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_formats/_array.py +0 -0
  42. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_formats/_enum.py +0 -0
  43. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_formats/_json.py +0 -0
  44. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_formats/_jsonl.py +0 -0
  45. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_formats/_schema.py +0 -0
  46. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_formats/_text.py +0 -0
  47. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_formats/_types.py +0 -0
  48. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_messages.py +0 -0
  49. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_resource.py +0 -0
  50. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_ai/_runtime.py +0 -0
  51. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_background.py +0 -0
  52. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_base.py +0 -0
  53. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_channel.py +0 -0
  54. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_compat.py +0 -0
  55. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_constants.py +0 -0
  56. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_context.py +0 -0
  57. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_dap.py +0 -0
  58. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_environment.py +0 -0
  59. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_extract_json.py +0 -0
  60. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_flow.py +0 -0
  61. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_http_client.py +0 -0
  62. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_logger.py +0 -0
  63. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_loop_cache.py +0 -0
  64. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_plugins.py +0 -0
  65. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_schema.py +0 -0
  66. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_trace/_adjusting_exporter.py +0 -0
  67. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_trace/_default_exporter.py +0 -0
  68. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_trace/_path.py +0 -0
  69. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_trace/_realtime_processor.py +0 -0
  70. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_trace/_suppress.py +0 -0
  71. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/_core/_tracing.py +0 -0
  72. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/embedder/__init__.py +0 -0
  73. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/evaluator/__init__.py +0 -0
  74. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/model/__init__.py +0 -0
  75. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/plugins/__init__.py +0 -0
  76. {genkit-0.6.0 → genkit-0.7.0}/src/genkit/py.typed +0 -0
  77. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/_tools_test.py +0 -0
  78. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/ai_registry_test.py +0 -0
  79. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/dap_test.py +0 -0
  80. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/document_test.py +0 -0
  81. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/dynamic_tools_generate_test.py +0 -0
  82. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/embedding_test.py +0 -0
  83. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/formats/array_test.py +0 -0
  84. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/formats/enum_test.py +0 -0
  85. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/formats/formats_test.py +0 -0
  86. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/formats/json_test.py +0 -0
  87. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/formats/jsonl_test.py +0 -0
  88. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/formats/text_test.py +0 -0
  89. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/generate_helpers_test.py +0 -0
  90. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/generate_interrupt_resume_test.py +0 -0
  91. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/generate_operation_test.py +0 -0
  92. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/genkit_api_test.py +0 -0
  93. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/message_utils_test.py +0 -0
  94. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/model_test.py +0 -0
  95. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/resource_integration_test.py +0 -0
  96. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/ai/resource_test.py +0 -0
  97. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/action_test.py +0 -0
  98. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/channel_test.py +0 -0
  99. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/environment_test.py +0 -0
  100. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/extract_test.py +0 -0
  101. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/http_client_test.py +0 -0
  102. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/latency_test.py +0 -0
  103. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/run_in_new_span_test.py +0 -0
  104. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/schema_test.py +0 -0
  105. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/status_types_test.py +0 -0
  106. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/trace/__init__.py +0 -0
  107. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/trace/adjusting_exporter_test.py +0 -0
  108. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/trace/default_exporter_test.py +0 -0
  109. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/core/trace/realtime_processor_test.py +0 -0
  110. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/testing_test.py +0 -0
  111. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/veneer/reflection_server_test.py +0 -0
  112. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/veneer/server_test.py +0 -0
  113. {genkit-0.6.0 → genkit-0.7.0}/tests/genkit/veneer/veneer_resource_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genkit
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Genkit AI Framework
5
5
  Project-URL: Bug Tracker, https://github.com/genkit-ai/genkit/issues
6
6
  Project-URL: Changelog, https://github.com/genkit-ai/genkit/blob/main/py/packages/genkit/CHANGELOG.md
@@ -76,7 +76,7 @@ license = "Apache-2.0"
76
76
  name = "genkit"
77
77
  readme = "README.md"
78
78
  requires-python = ">=3.10"
79
- version = "0.6.0"
79
+ version = "0.7.0"
80
80
 
81
81
  [project.optional-dependencies]
82
82
  flask = ["genkit-plugin-flask"]
@@ -16,7 +16,7 @@
16
16
 
17
17
  """Genkit — Build AI-powered applications."""
18
18
 
19
- from genkit._ai._aio import ActionKind, ActionRunContext, Genkit
19
+ from genkit._ai._aio import ActionKind, Genkit
20
20
  from genkit._ai._prompt import (
21
21
  ExecutablePrompt,
22
22
  ModelStreamResponse,
@@ -30,7 +30,7 @@ from genkit._ai._tools import (
30
30
  restart_tool,
31
31
  tool,
32
32
  )
33
- from genkit._core._action import Action, StreamResponse
33
+ from genkit._core._action import Action, ActionRunContext, StreamResponse
34
34
  from genkit._core._error import GenkitError, PublicError
35
35
  from genkit._core._model import Document
36
36
  from genkit._core._plugin import Plugin
@@ -41,6 +41,8 @@ from genkit._core._typing import (
41
41
  Media,
42
42
  MediaPart,
43
43
  Metadata,
44
+ MiddlewareRef,
45
+ MultipartToolResponse,
44
46
  Part,
45
47
  ReasoningPart,
46
48
  Role,
@@ -99,6 +101,7 @@ __all__ = [
99
101
  # Errors
100
102
  'GenkitError',
101
103
  'PublicError',
104
+ # Tools
102
105
  'Interrupt',
103
106
  'Tool',
104
107
  'respond_to_interrupt',
@@ -115,6 +118,7 @@ __all__ = [
115
118
  'Media',
116
119
  'MediaPart',
117
120
  'Message',
121
+ 'MultipartToolResponse',
118
122
  'Part',
119
123
  'Role',
120
124
  'Stage',
@@ -131,6 +135,8 @@ __all__ = [
131
135
  'DocumentPart',
132
136
  # Plugin interface
133
137
  'Plugin',
138
+ # Middleware references (wire form for use= parameter)
139
+ 'MiddlewareRef',
134
140
  # AI runtime
135
141
  'ActionKind',
136
142
  'ActionRunContext',
@@ -44,12 +44,16 @@ from genkit._ai._evaluator import (
44
44
  )
45
45
  from genkit._ai._formats import built_in_formats
46
46
  from genkit._ai._formats._types import FormatDef
47
- from genkit._ai._generate import define_generate_action, generate_action, registry_with_inline_tools
47
+ from genkit._ai._generate import (
48
+ define_generate_action,
49
+ generate_action,
50
+ register_middleware,
51
+ register_tools,
52
+ )
48
53
  from genkit._ai._model import (
49
54
  Message,
50
55
  ModelConfig,
51
56
  ModelFn,
52
- ModelMiddleware,
53
57
  ModelResponse,
54
58
  ModelResponseChunk,
55
59
  define_model,
@@ -71,7 +75,7 @@ from genkit._ai._resource import (
71
75
  define_resource,
72
76
  )
73
77
  from genkit._ai._tools import Tool, define_interrupt, define_tool
74
- from genkit._core._action import Action, ActionKind, ActionRunContext
78
+ from genkit._core._action import Action, ActionKind, get_current_context
75
79
  from genkit._core._background import (
76
80
  BackgroundAction,
77
81
  CancelModelOpFn,
@@ -90,6 +94,11 @@ from genkit._core._dap import (
90
94
  from genkit._core._environment import is_dev_environment
91
95
  from genkit._core._error import GenkitError
92
96
  from genkit._core._logger import get_logger
97
+ from genkit._core._middleware import (
98
+ BaseMiddleware,
99
+ GenerateMiddleware,
100
+ _validate_middleware_key_segment,
101
+ )
93
102
  from genkit._core._model import Document
94
103
  from genkit._core._plugin import Plugin
95
104
  from genkit._core._reflection import ReflectionServer, ServerSpec, create_reflection_asgi_app
@@ -102,6 +111,7 @@ from genkit._core._typing import (
102
111
  EmbedRequest,
103
112
  EvalRequest,
104
113
  EvalResponse,
114
+ MiddlewareRef,
105
115
  ModelInfo,
106
116
  Operation,
107
117
  Part,
@@ -122,6 +132,7 @@ ChunkT = TypeVar('ChunkT')
122
132
 
123
133
  R = TypeVar('R')
124
134
  T = TypeVar('T')
135
+ MiddlewareT = TypeVar('MiddlewareT', bound=BaseMiddleware)
125
136
 
126
137
 
127
138
  def _model_supports_long_running(model_action: Action) -> bool:
@@ -157,6 +168,7 @@ class Genkit:
157
168
  self._initialize_registry(model, plugins)
158
169
  # Ensure the default generate action is registered for async usage.
159
170
  define_generate_action(self.registry)
171
+ self._register_plugin_middleware(plugins)
160
172
  # In dev mode, start the reflection server immediately in a background
161
173
  # daemon thread so it's available regardless of which web framework (or
162
174
  # none) the user chooses.
@@ -269,6 +281,35 @@ class Genkit:
269
281
 
270
282
  return wrapper
271
283
 
284
+ def define_middleware(
285
+ self,
286
+ cls: type[BaseMiddleware],
287
+ *,
288
+ name: str,
289
+ description: str | None = None,
290
+ ) -> GenerateMiddleware:
291
+ """Register a middleware class on this app's registry under ``name``."""
292
+ res = _validate_middleware_key_segment(name)
293
+ if res.errored:
294
+ raise ValueError(f'middleware name {res.error_message}')
295
+ desc = GenerateMiddleware(cls=cls, name=name, description=description)
296
+ self.registry.register_value('middleware', name, desc)
297
+ return desc
298
+
299
+ def middleware(
300
+ self,
301
+ *,
302
+ name: str,
303
+ description: str | None = None,
304
+ ) -> Callable[[type[MiddlewareT]], type[MiddlewareT]]:
305
+ """Decorator that registers a custom middleware on this app's registry."""
306
+
307
+ def decorator(cls: type[MiddlewareT]) -> type[MiddlewareT]:
308
+ self.define_middleware(cls, name=name, description=description)
309
+ return cls
310
+
311
+ return decorator
312
+
272
313
  def define_interrupt(
273
314
  self,
274
315
  name: str,
@@ -425,7 +466,7 @@ class Genkit:
425
466
  metadata: dict[str, object] | None = None,
426
467
  tools: Sequence[str | Tool] | None = None,
427
468
  tool_choice: ToolChoice | None = None,
428
- use: list[ModelMiddleware] | None = None,
469
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
429
470
  docs: list[Document] | None = None,
430
471
  input_schema: type[InputT],
431
472
  output_schema: type[OutputT],
@@ -453,7 +494,7 @@ class Genkit:
453
494
  metadata: dict[str, object] | None = None,
454
495
  tools: Sequence[str | Tool] | None = None,
455
496
  tool_choice: ToolChoice | None = None,
456
- use: list[ModelMiddleware] | None = None,
497
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
457
498
  docs: list[Document] | None = None,
458
499
  input_schema: type[InputT],
459
500
  output_schema: dict[str, object] | str | None = None,
@@ -481,7 +522,7 @@ class Genkit:
481
522
  metadata: dict[str, object] | None = None,
482
523
  tools: Sequence[str | Tool] | None = None,
483
524
  tool_choice: ToolChoice | None = None,
484
- use: list[ModelMiddleware] | None = None,
525
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
485
526
  docs: list[Document] | None = None,
486
527
  input_schema: dict[str, object] | str | None = None,
487
528
  output_schema: type[OutputT],
@@ -509,7 +550,7 @@ class Genkit:
509
550
  metadata: dict[str, object] | None = None,
510
551
  tools: Sequence[str | Tool] | None = None,
511
552
  tool_choice: ToolChoice | None = None,
512
- use: list[ModelMiddleware] | None = None,
553
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
513
554
  docs: list[Document] | None = None,
514
555
  input_schema: dict[str, object] | str | None = None,
515
556
  output_schema: dict[str, object] | str | None = None,
@@ -535,7 +576,7 @@ class Genkit:
535
576
  metadata: dict[str, object] | None = None,
536
577
  tools: Sequence[str | Tool] | None = None,
537
578
  tool_choice: ToolChoice | None = None,
538
- use: list[ModelMiddleware] | None = None,
579
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
539
580
  docs: list[Document] | None = None,
540
581
  input_schema: type | dict[str, object] | str | None = None,
541
582
  output_schema: type | dict[str, object] | str | None = None,
@@ -725,6 +766,14 @@ class Genkit:
725
766
  else:
726
767
  raise ValueError(f'Invalid {plugin=} provided to Genkit: must be of type `genkit.ai.Plugin`')
727
768
 
769
+ def _register_plugin_middleware(self, plugins: list[Plugin] | None) -> None:
770
+ """Register middleware descriptors returned by ``Plugin.list_middleware``."""
771
+ if not plugins:
772
+ return
773
+ for plugin in plugins:
774
+ for desc in plugin.list_middleware():
775
+ self.registry.register_value('middleware', desc.name, desc)
776
+
728
777
  def run_main(self, coro: Coroutine[Any, Any, T]) -> T | None:
729
778
  """Run the user's main coroutine, blocking in dev mode for the reflection server."""
730
779
  if not is_dev_environment():
@@ -799,7 +848,7 @@ class Genkit:
799
848
  output_content_type: str | None = None,
800
849
  output_instructions: str | None = None,
801
850
  output_constrained: bool | None = None,
802
- use: list[ModelMiddleware] | None = None,
851
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
803
852
  docs: list[Document] | None = None,
804
853
  ) -> ModelResponse[OutputT]: ...
805
854
 
@@ -826,7 +875,7 @@ class Genkit:
826
875
  output_content_type: str | None = None,
827
876
  output_instructions: str | None = None,
828
877
  output_constrained: bool | None = None,
829
- use: list[ModelMiddleware] | None = None,
878
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
830
879
  docs: list[Document] | None = None,
831
880
  ) -> ModelResponse[Any]: ...
832
881
 
@@ -851,7 +900,7 @@ class Genkit:
851
900
  output_content_type: str | None = None,
852
901
  output_instructions: str | None = None,
853
902
  output_constrained: bool | None = None,
854
- use: list[ModelMiddleware] | None = None,
903
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
855
904
  docs: list[Document] | None = None,
856
905
  ) -> ModelResponse[Any]:
857
906
  """Generate text or structured data using a language model.
@@ -860,6 +909,11 @@ class Genkit:
860
909
  is covariant: ``list[Tool]`` or ``list[str]`` are both assignable to
861
910
  ``Sequence[str | Tool]``, but not to ``list[str | Tool]``.
862
911
  """
912
+ # One call-scoped registry layer holds anything inline (tools +
913
+ # middleware) so it dies with the call and stays out of self.registry.
914
+ child_registry = self.registry.new_child()
915
+ await register_tools(child_registry, tools)
916
+ refs = register_middleware(child_registry, use)
863
917
  prompt_config = PromptConfig(
864
918
  model=model,
865
919
  prompt=prompt,
@@ -879,14 +933,13 @@ class Genkit:
879
933
  output_schema=output_schema,
880
934
  output_constrained=output_constrained,
881
935
  docs=docs,
936
+ use=refs,
882
937
  )
883
- registry = await registry_with_inline_tools(self.registry, prompt_config.tools)
884
- gen_options = await to_generate_action_options(registry, prompt_config)
938
+ gen_options = await to_generate_action_options(child_registry, prompt_config)
885
939
  return await generate_action(
886
- registry,
940
+ child_registry,
887
941
  gen_options,
888
- middleware=use,
889
- context=context if context else ActionRunContext._current_context(), # pyright: ignore[reportPrivateUsage]
942
+ context=context if context else get_current_context(),
890
943
  )
891
944
 
892
945
  # Overload: output_schema=type[T] -> ModelStreamResponse[T]
@@ -912,7 +965,7 @@ class Genkit:
912
965
  output_content_type: str | None = None,
913
966
  output_instructions: str | None = None,
914
967
  output_constrained: bool | None = None,
915
- use: list[ModelMiddleware] | None = None,
968
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
916
969
  docs: list[Document] | None = None,
917
970
  timeout: float | None = None,
918
971
  ) -> ModelStreamResponse[OutputT]: ...
@@ -940,7 +993,7 @@ class Genkit:
940
993
  output_content_type: str | None = None,
941
994
  output_instructions: str | None = None,
942
995
  output_constrained: bool | None = None,
943
- use: list[ModelMiddleware] | None = None,
996
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
944
997
  docs: list[Document] | None = None,
945
998
  timeout: float | None = None,
946
999
  ) -> ModelStreamResponse[Any]: ...
@@ -966,7 +1019,7 @@ class Genkit:
966
1019
  output_content_type: str | None = None,
967
1020
  output_instructions: str | None = None,
968
1021
  output_constrained: bool | None = None,
969
- use: list[ModelMiddleware] | None = None,
1022
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
970
1023
  docs: list[Document] | None = None,
971
1024
  timeout: float | None = None,
972
1025
  ) -> ModelStreamResponse[Any]:
@@ -974,6 +1027,11 @@ class Genkit:
974
1027
  channel: Channel[ModelResponseChunk, ModelResponse[Any]] = Channel(timeout=timeout)
975
1028
 
976
1029
  async def _run_generate() -> ModelResponse[Any]:
1030
+ # One call-scoped registry layer holds anything inline (tools +
1031
+ # middleware) so it dies with the call and stays out of self.registry.
1032
+ child_registry = self.registry.new_child()
1033
+ await register_tools(child_registry, tools)
1034
+ refs = register_middleware(child_registry, use)
977
1035
  prompt_config = PromptConfig(
978
1036
  model=model,
979
1037
  prompt=prompt,
@@ -993,15 +1051,14 @@ class Genkit:
993
1051
  output_schema=output_schema,
994
1052
  output_constrained=output_constrained,
995
1053
  docs=docs,
1054
+ use=refs,
996
1055
  )
997
- registry = await registry_with_inline_tools(self.registry, prompt_config.tools)
998
- gen_options = await to_generate_action_options(registry, prompt_config)
1056
+ gen_options = await to_generate_action_options(child_registry, prompt_config)
999
1057
  return await generate_action(
1000
- registry,
1058
+ child_registry,
1001
1059
  gen_options,
1002
1060
  on_chunk=lambda c: channel.send(c),
1003
- middleware=use,
1004
- context=context if context else ActionRunContext._current_context(), # pyright: ignore[reportPrivateUsage]
1061
+ context=context if context else get_current_context(),
1005
1062
  )
1006
1063
 
1007
1064
  response_future: asyncio.Future[ModelResponse[Any]] = asyncio.create_task(_run_generate())
@@ -1120,7 +1177,7 @@ class Genkit:
1120
1177
  @staticmethod
1121
1178
  def current_context() -> dict[str, Any] | None:
1122
1179
  """Get the current execution context, or None if not in an action."""
1123
- return ActionRunContext._current_context() # pyright: ignore[reportPrivateUsage]
1180
+ return get_current_context()
1124
1181
 
1125
1182
  async def run(
1126
1183
  self,
@@ -1184,7 +1241,7 @@ class Genkit:
1184
1241
  output_content_type: str | None = None,
1185
1242
  output_instructions: str | None = None,
1186
1243
  output_constrained: bool | None = None,
1187
- use: list[ModelMiddleware] | None = None,
1244
+ use: Sequence[BaseMiddleware | MiddlewareRef] | None = None,
1188
1245
  docs: list[Document] | None = None,
1189
1246
  ) -> Operation:
1190
1247
  """Generate content using a long-running model, returning an Operation to poll."""