@genkit-ai/ai
Version:
Genkit AI framework generative AI APIs.
1 lines • 9.22 kB
Source Map (JSON)
{"version":3,"sources":["../src/resource.ts"],"sourcesContent":["/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n action,\n Action,\n ActionContext,\n GenkitError,\n isAction,\n z,\n} from '@genkit-ai/core';\nimport { Registry } from '@genkit-ai/core/registry';\nimport uriTemplate from 'uri-templates';\nimport { PartSchema } from './model-types.js';\n\n/**\n * Options for defining a resource.\n */\nexport interface ResourceOptions {\n /**\n * Resource name. If not specified, uri or template will be used as name.\n */\n name?: string;\n\n /**\n * The URI of the resource. Can contain template variables.\n */\n uri?: string;\n\n /**\n * The URI template (ex. `my://resource/{id}`). See RFC6570 for specification.\n */\n template?: string;\n\n /**\n * A description of the resource.\n */\n description?: string;\n\n /**\n * Resource metadata.\n */\n metadata?: Record<string, any>;\n}\n\nexport const ResourceInputSchema = z.object({\n uri: z.string(),\n});\n\nexport type ResourceInput = z.infer<typeof ResourceInputSchema>;\n\nexport const ResourceOutputSchema = z.object({\n content: z.array(PartSchema),\n});\n\nexport type ResourceOutput = z.infer<typeof ResourceOutputSchema>;\n\n/**\n * A function that returns parts for a given resource.\n */\nexport type ResourceFn = (\n input: ResourceInput,\n ctx: ActionContext\n) => ResourceOutput | Promise<ResourceOutput>;\n\n/**\n * A resource action.\n */\nexport interface ResourceAction\n extends Action<typeof ResourceInputSchema, typeof ResourceOutputSchema> {\n matches(input: ResourceInput): boolean;\n}\n\n/**\n * Defines a resource.\n *\n * @param registry The registry to register the resource with.\n * @param opts The resource options.\n * @param fn The resource function.\n * @returns The resource action.\n */\nexport function defineResource(\n registry: Registry,\n opts: ResourceOptions,\n fn: ResourceFn\n): ResourceAction {\n const action = dynamicResource(opts, fn);\n action.matches = createMatcher(opts.uri, opts.template);\n registry.registerAction('resource', action);\n return action;\n}\n\n/**\n * A dynamic action with a `resource` type. Dynamic resources are detached actions -- not associated with any registry.\n */\nexport type DynamicResourceAction = ResourceAction & {\n __action: {\n metadata: {\n type: 'resource';\n };\n };\n /** @deprecated no-op, for backwards compatibility only. */\n attach(registry: Registry): ResourceAction;\n matches(input: ResourceInput): boolean;\n};\n\n/**\n * Finds a matching resource in the registry. If not found returns undefined.\n */\nexport async function findMatchingResource(\n registry: Registry,\n input: ResourceInput\n): Promise<ResourceAction | undefined> {\n for (const actKeys of Object.keys(await registry.listResolvableActions())) {\n if (actKeys.startsWith('/resource/')) {\n const resource = (await registry.lookupAction(actKeys)) as ResourceAction;\n if (resource.matches(input)) {\n return resource;\n }\n }\n }\n return undefined;\n}\n\n/** Checks whether provided object is a dynamic resource. */\nexport function isDynamicResourceAction(t: unknown): t is ResourceAction {\n return isAction(t) && !t.__registry;\n}\n\n/**\n * Defines a dynamic resource. Dynamic resources are just like regular resources but will not be\n * registered in the Genkit registry and can be defined dynamically at runtime.\n */\nexport function resource(\n opts: ResourceOptions,\n fn: ResourceFn\n): ResourceAction {\n return dynamicResource(opts, fn);\n}\n\n/**\n * Defines a dynamic resource. Dynamic resources are just like regular resources but will not be\n * registered in the Genkit registry and can be defined dynamically at runtime.\n */\nexport function dynamicResource(\n opts: ResourceOptions,\n fn: ResourceFn\n): DynamicResourceAction {\n const uri = opts.uri ?? opts.template;\n if (!uri) {\n throw new GenkitError({\n status: 'INVALID_ARGUMENT',\n message: `must specify either url or template options`,\n });\n }\n const matcher = createMatcher(opts.uri, opts.template);\n\n const act = action(\n {\n actionType: 'resource',\n name: opts.name ?? uri,\n description: opts.description,\n inputSchema: ResourceInputSchema,\n outputSchema: ResourceOutputSchema,\n metadata: {\n resource: {\n uri: opts.uri,\n template: opts.template,\n },\n ...opts.metadata,\n type: 'resource',\n dynamic: true,\n },\n },\n async (input, ctx) => {\n const templateMatch = matcher(input);\n if (!templateMatch) {\n throw new GenkitError({\n status: 'INVALID_ARGUMENT',\n message: `input ${input} did not match template ${uri}`,\n });\n }\n const parts = await fn(input, ctx);\n parts.content.map((p) => {\n if (!p.metadata) {\n p.metadata = {};\n }\n if (p.metadata?.resource) {\n if (!(p.metadata as any).resource.parent) {\n (p.metadata as any).resource.parent = {\n uri: input.uri,\n };\n if (opts.template) {\n (p.metadata as any).resource.parent.template = opts.template;\n }\n }\n } else {\n (p.metadata as any).resource = {\n uri: input.uri,\n };\n if (opts.template) {\n (p.metadata as any).resource.template = opts.template;\n }\n }\n return p;\n });\n return parts;\n }\n ) as DynamicResourceAction;\n\n act.matches = matcher;\n act.attach = (_: Registry) => act;\n return act;\n}\n\nfunction createMatcher(\n uriOpt: string | undefined,\n templateOpt: string | undefined\n): (input: ResourceInput) => boolean {\n // TODO: normalize resource URI during comparisons\n // foo://bar?baz=1&qux=2 and foo://bar?qux=2&baz=1 are equivalent URIs but would not match.\n if (uriOpt) {\n return (input: ResourceInput) => input.uri === uriOpt;\n }\n\n if (templateOpt) {\n const template = uriTemplate(templateOpt);\n return (input: ResourceInput) => template!.fromUri(input.uri) !== undefined;\n }\n\n throw new GenkitError({\n status: 'INVALID_ARGUMENT',\n message: 'must specify either url or template options',\n });\n}\n"],"mappings":"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","names":["action","resource"]}