Skip to content

fix(js,py): Export ResourcePartSchema through genkit-tools #3239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions genkit-tools/common/src/types/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const EmptyPartSchema = z.object({
metadata: z.record(z.unknown()).optional(),
custom: z.record(z.unknown()).optional(),
reasoning: z.never().optional(),
resource: z.never().optional(),
});

/**
Expand Down Expand Up @@ -147,6 +148,20 @@ export const CustomPartSchema = EmptyPartSchema.extend({
*/
export type CustomPart = z.infer<typeof CustomPartSchema>;

/**
* Zod schema of a resource part.
*/
export const ResourcePartSchema = EmptyPartSchema.extend({
resource: z.object({
uri: z.string(),
}),
});

/**
* Resource part.
*/
export type ResourcePart = z.infer<typeof ResourcePartSchema>;

// Disclaimer: genkit/js/ai/document.ts defines the following schema, type pair
// as PartSchema and Part, respectively. genkit-tools cannot retain those names
// due to it clashing with similar schema in model.ts, and genkit-tools
Expand Down
5 changes: 5 additions & 0 deletions genkit-tools/common/src/types/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ import {
DocumentDataSchema,
MediaPartSchema,
ReasoningPartSchema,
ResourcePartSchema,
TextPartSchema,
ToolRequestPartSchema,
ToolResponsePartSchema,
type CustomPart,
type DataPart,
type MediaPart,
type ResourcePart,
type TextPart,
type ToolRequestPart,
type ToolResponsePart,
Expand All @@ -34,12 +36,14 @@ export {
CustomPartSchema,
DataPartSchema,
MediaPartSchema,
ResourcePartSchema,
TextPartSchema,
ToolRequestPartSchema,
ToolResponsePartSchema,
type CustomPart,
type DataPart,
type MediaPart,
type ResourcePart,
type TextPart,
type ToolRequestPart,
type ToolResponsePart,
Expand Down Expand Up @@ -77,6 +81,7 @@ export const PartSchema = z.union([
DataPartSchema,
CustomPartSchema,
ReasoningPartSchema,
ResourcePartSchema,
]);

/**
Expand Down
69 changes: 69 additions & 0 deletions genkit-tools/genkit-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
},
"reasoning": {
"not": {}
},
"resource": {
"not": {}
}
},
"required": [
Expand Down Expand Up @@ -59,6 +62,9 @@
},
"reasoning": {
"$ref": "#/$defs/CustomPart/properties/reasoning"
},
"resource": {
"$ref": "#/$defs/CustomPart/properties/resource"
}
},
"additionalProperties": false
Expand Down Expand Up @@ -118,6 +124,9 @@
},
"reasoning": {
"$ref": "#/$defs/CustomPart/properties/reasoning"
},
"resource": {
"$ref": "#/$defs/CustomPart/properties/resource"
}
},
"required": [
Expand Down Expand Up @@ -166,13 +175,61 @@
},
"reasoning": {
"type": "string"
},
"resource": {
"$ref": "#/$defs/CustomPart/properties/resource"
}
},
"required": [
"reasoning"
],
"additionalProperties": false
},
"ResourcePart": {
"type": "object",
"properties": {
"text": {
"$ref": "#/$defs/CustomPart/properties/text"
},
"media": {
"$ref": "#/$defs/CustomPart/properties/media"
},
"toolRequest": {
"$ref": "#/$defs/CustomPart/properties/toolRequest"
},
"toolResponse": {
"$ref": "#/$defs/CustomPart/properties/toolResponse"
},
"data": {
"$ref": "#/$defs/CustomPart/properties/data"
},
"metadata": {
"$ref": "#/$defs/CustomPart/properties/metadata"
},
"custom": {
"$ref": "#/$defs/DataPart/properties/custom"
},
"reasoning": {
"$ref": "#/$defs/CustomPart/properties/reasoning"
},
"resource": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
},
"required": [
"uri"
],
"additionalProperties": false
}
},
"required": [
"resource"
],
"additionalProperties": false
},
"TextPart": {
"type": "object",
"properties": {
Expand All @@ -199,6 +256,9 @@
},
"reasoning": {
"$ref": "#/$defs/CustomPart/properties/reasoning"
},
"resource": {
"$ref": "#/$defs/CustomPart/properties/resource"
}
},
"required": [
Expand Down Expand Up @@ -232,6 +292,9 @@
},
"reasoning": {
"$ref": "#/$defs/CustomPart/properties/reasoning"
},
"resource": {
"$ref": "#/$defs/CustomPart/properties/resource"
}
},
"required": [
Expand Down Expand Up @@ -281,6 +344,9 @@
},
"reasoning": {
"$ref": "#/$defs/CustomPart/properties/reasoning"
},
"resource": {
"$ref": "#/$defs/CustomPart/properties/resource"
}
},
"required": [
Expand Down Expand Up @@ -1138,6 +1204,9 @@
},
{
"$ref": "#/$defs/ReasoningPart"
},
{
"$ref": "#/$defs/ResourcePart"
}
]
},
Expand Down
2 changes: 1 addition & 1 deletion js/testapps/flow-simple-ai/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,7 @@ ai.defineResource(
description: 'provides my resource',
},
async (input) => {
return { content: [{ text: `resource ${input}` }] };
return { content: [{ text: `resource ${input.uri}` }] };
}
);

Expand Down
43 changes: 41 additions & 2 deletions py/packages/genkit/src/genkit/core/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class CustomPart(BaseModel):
metadata: dict[str, Any] | None = None
custom: dict[str, Any]
reasoning: Any | None = None
resource: Any | None = None


class Media(BaseModel):
Expand All @@ -66,6 +67,13 @@ class Media(BaseModel):
url: str


class Resource1(BaseModel):
"""Model for resource1 data."""

model_config = ConfigDict(extra='forbid', populate_by_name=True)
uri: str


class ToolRequest(BaseModel):
"""Model for toolrequest data."""

Expand Down Expand Up @@ -505,6 +513,12 @@ class Reasoning(RootModel[Any]):
root: Any


class Resource(RootModel[Any]):
"""Root model for resource."""

root: Any


class Text(RootModel[Any]):
"""Root model for text."""

Expand Down Expand Up @@ -601,6 +615,7 @@ class DataPart(BaseModel):
metadata: Metadata | None = None
custom: dict[str, Any] | None = None
reasoning: Reasoning | None = None
resource: Resource | None = None


class MediaPart(BaseModel):
Expand All @@ -615,6 +630,7 @@ class MediaPart(BaseModel):
metadata: Metadata | None = None
custom: Custom | None = None
reasoning: Reasoning | None = None
resource: Resource | None = None


class ReasoningPart(BaseModel):
Expand All @@ -629,6 +645,22 @@ class ReasoningPart(BaseModel):
metadata: Metadata | None = None
custom: Custom | None = None
reasoning: str
resource: Resource | None = None


class ResourcePart(BaseModel):
"""Model for resourcepart data."""

model_config = ConfigDict(extra='forbid', populate_by_name=True)
text: Text | None = None
media: MediaModel | None = None
tool_request: ToolRequestModel | None = Field(None, alias='toolRequest')
tool_response: ToolResponseModel | None = Field(None, alias='toolResponse')
data: Data | None = None
metadata: Metadata | None = None
custom: Custom | None = None
reasoning: Reasoning | None = None
resource: Resource1


class TextPart(BaseModel):
Expand All @@ -643,6 +675,7 @@ class TextPart(BaseModel):
metadata: Metadata | None = None
custom: Custom | None = None
reasoning: Reasoning | None = None
resource: Resource | None = None


class ToolRequestPart(BaseModel):
Expand All @@ -657,6 +690,7 @@ class ToolRequestPart(BaseModel):
metadata: Metadata | None = None
custom: Custom | None = None
reasoning: Reasoning | None = None
resource: Resource | None = None


class ToolResponsePart(BaseModel):
Expand All @@ -671,6 +705,7 @@ class ToolResponsePart(BaseModel):
metadata: Metadata | None = None
custom: Custom | None = None
reasoning: Reasoning | None = None
resource: Resource | None = None


class EmbedResponse(BaseModel):
Expand Down Expand Up @@ -719,11 +754,15 @@ class Resume(BaseModel):


class Part(
RootModel[TextPart | MediaPart | ToolRequestPart | ToolResponsePart | DataPart | CustomPart | ReasoningPart]
RootModel[
TextPart | MediaPart | ToolRequestPart | ToolResponsePart | DataPart | CustomPart | ReasoningPart | ResourcePart
]
):
"""Root model for part."""

root: TextPart | MediaPart | ToolRequestPart | ToolResponsePart | DataPart | CustomPart | ReasoningPart
root: (
TextPart | MediaPart | ToolRequestPart | ToolResponsePart | DataPart | CustomPart | ReasoningPart | ResourcePart
)


class Link(BaseModel):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,7 @@ def get_default_model_info(name: str) -> ModelInfo:
supports=DEFAULT_SUPPORTS,
)


def get_default_openai_model_info(name: str) -> ModelInfo:
"""Gets the default model info given a name."""
return ModelInfo(
label=f"OpenAI - {name}",
supports={'multiturn': True}
)
return ModelInfo(label=f'OpenAI - {name}', supports={'multiturn': True})
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,11 @@ def open_ai_name(name: str) -> str:
"""
return f'openai/{name}'


def default_openai_metadata(name: str) -> dict[str, Any]:
return {
'model': {
'label': f"OpenAI - {name}",
'supports': {'multiturn': True}
},
}
'model': {'label': f'OpenAI - {name}', 'supports': {'multiturn': True}},
}


class OpenAI(Plugin):
Expand Down Expand Up @@ -131,7 +129,6 @@ def resolve_action( # noqa: B027
kind: ActionKind,
name: str,
) -> None:

if kind is not ActionKind.MODEL:
return None

Expand Down
10 changes: 3 additions & 7 deletions py/plugins/compat-oai/tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ def test_openai_plugin_initialize() -> None:

@pytest.mark.parametrize(
'kind, name',
[
(ActionKind.MODEL, 'gpt-3.5-turbo')
],
[(ActionKind.MODEL, 'gpt-3.5-turbo')],
)
def test_openai_plugin_resolve_action(kind, name):
"""Unit Tests for resolve action method."""
Expand All @@ -72,7 +70,7 @@ def test_openai_plugin_resolve_action(kind, name):
],
'system_role': True,
'tools': True,
}
},
},
},
)
Expand Down Expand Up @@ -108,9 +106,7 @@ def test_openai_plugin_list_actions() -> None:

@pytest.mark.parametrize(
'kind, name',
[
(ActionKind.MODEL, "model_doesnt_exist")
],
[(ActionKind.MODEL, 'model_doesnt_exist')],
)
def test_openai_plugin_resolve_action_not_found(kind, name):
"""Unit Tests for resolve action method."""
Expand Down
Loading