UNPKG

@genkit-ai/ai

Version:

Genkit AI framework generative AI APIs.

1 lines 11.6 kB
{"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 * A reference to a resource in the form of a name or a ResourceAction.\n */\nexport type ResourceArgument = ResourceAction | string;\n\nexport async function resolveResources(\n registry: Registry,\n resources?: ResourceArgument[]\n): Promise<ResourceAction[]> {\n if (!resources || resources.length === 0) {\n return [];\n }\n\n return await Promise.all(\n resources.map(async (ref): Promise<ResourceAction> => {\n if (typeof ref === 'string') {\n return await lookupResourceByName(registry, ref);\n } else if (isAction(ref)) {\n return ref;\n }\n throw new Error('Resources must be strings, or actions');\n })\n );\n}\n\nexport async function lookupResourceByName(\n registry: Registry,\n name: string\n): Promise<ResourceAction> {\n const resource =\n (await registry.lookupAction(name)) ||\n (await registry.lookupAction(`/resource/${name}`)) ||\n (await registry.lookupAction(`/dynamic-action-provider/${name}`));\n if (!resource) {\n throw new Error(`Resource ${name} not found`);\n }\n return resource as ResourceAction;\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 action.__action.metadata.dynamic = false;\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 resources: ResourceAction[],\n input: ResourceInput\n): Promise<ResourceAction | undefined> {\n // First look in any resources explicitly listed in the generate request\n for (const res of resources) {\n if (res.matches(input)) {\n return res;\n }\n }\n\n // Then search the registry\n for (const registryKey of Object.keys(\n await registry.listResolvableActions()\n )) {\n // We decided not to look in DAP actions because they might be slow.\n // DAP actions with resources will only be found if they are listed in the\n // resources section, and then they will be found above.\n if (registryKey.startsWith('/resource/')) {\n const resource = (await registry.lookupAction(\n registryKey\n )) as ResourceAction;\n\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.__action?.metadata?.dynamic === true;\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 *\n * @deprecated renamed to {@link resource}.\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":["resource","action"]}