@sanity/assist
Version:
You create the instructions; Sanity AI Assist does the rest.
699 lines • 24.6 kB
TypeScript
import * as _$sanity from "sanity";
import { CurrentUser, DocumentFieldActionDivider, DocumentFieldActionGroup, DocumentFieldActionItem, ObjectSchemaType, Path, SanityClient, SanityDocumentLike, SchemaType } from "sanity";
import { SanityClient as SanityClient$1 } from "@sanity/client";
import { AgentActionPath } from "/home/runner/work/plugins/plugins/node_modules/.pnpm/@sanity+client@7.21.0/node_modules/@sanity/client/dist/stega.js";
import { PortableTextBlock, PortableTextMarkDefinition, PortableTextSpan } from "@portabletext/types";
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
interface AssistConfig {
/**
* As of v3.0 Assist can write to date and datetime fields.
*
* If this function is omitted from config, the plugin will use the default timeZone and locale
* in the browser:
*
* ```ts
* const {timeZone, locale} = Intl.DateTimeFormat().resolvedOptions()
* ```
*
* The function will be called any time an instruction runs.
*
* @see #LocaleSettings.locale
* @see #LocaleSettings.timeZone
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#getcanonicalocales
* @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
*/
localeSettings?: (context: LocaleSettingsContext) => LocaleSettings;
/**
* The max depth for document paths AI Assist will write to.
*
* Depth is based on field path segments:
* - `title` has depth 1
* - `array[_key="no"].title` has depth 3
*
* Be careful not to set this too high in studios with recursive document schemas, as it could have
* negative impact on performance.
*
* Depth will be counted from the field the instruction is run from. For example, if an instruction
* is attached to depth 6, the count starts from there (at 0, not at 6).
*
* Default: 4
*/
maxPathDepth?: number;
/**
* Influences how much the output of an instruction will vary.
*
* Min: 0 – re-running an instruction will often produce the same outcomes
* Max: 1 – re-running an instruction can produce wildly different outcomes
*
* This parameter applies to _all_ instructions in the studio.
*
* Prior to v3.0, this defaulted to 0
*
* Default: 0.3
*/
temperature?: number;
}
interface LocaleSettingsContext {
user: CurrentUser;
defaultSettings: LocaleSettings;
}
interface LocaleSettings {
/**
* A valid Unicode BCP 47 locale identifier used to interpret and format
* natural language inputs and date output. Examples include "en-US", "fr-FR", or "ja-JP".
*
* This affects how phrases like "next Friday" or "in two weeks" are parsed,
* and how resulting dates are presented (e.g., 12-hour vs 24-hour format).
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#getcanonicalocales
*/
locale: string;
/**
* A valid IANA time zone identifier used to resolve relative and absolute
* date expressions to a specific point in time. Examples include
* "America/New_York", "Europe/Paris", or "Asia/Tokyo".
*
* This ensures phrases like "tomorrow at 9am" are interpreted correctly
* based on the user's local time.
*
* @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
*/
timeZone: string;
}
interface AgentActionConditionalPath {
path: AgentActionPath;
readOnly: boolean;
hidden: boolean;
}
interface AssistFieldActionProps {
/**
* `actionType` will be `document` for action invoked from the top right document action menu, and
* `field` when invoked from a field action menu.
*/
actionType: 'document' | 'field';
/**
* This is the id of the current document pane; it contains `drafts.`or `versions. prefix` ect depending on context.
* Use this for `documentId` when calling any `client.agent.action`.
*
* It is generally recommended to call actions from the studio like this:
* ```ts
* await client.agent.action.generate({
* targetDocument: {
* operation: 'createIfNotExists',
* _id: props.documentIdForAction,
* _type: props.documentSchemaType.name,
* initialValues: props.getDocumentValue()
* },
* //...
* })
* ```
*/
documentIdForAction: string;
/**
* Schema type of the current document.
* @see documentIdForAction
*/
documentSchemaType: ObjectSchemaType;
/**
* Returns the current document value.
*
* Prefer passing this function to your hooks instead of passing the document value directly to avoid unnecessary re-renders.
* @see documentIdForAction
*/
getDocumentValue: () => SanityDocumentLike;
/**
* Returns the current readOnly and hidden state of all conditional members in the current document form.
*
* Intended to be passed to agent actions `conditionalPaths.paths`.
*/
getConditionalPaths: () => AgentActionConditionalPath[];
/**
* `schemaId` for the current workspace.
*
* Note: the workspace schema has to be deployed using `sanity schema deploy` or `sanity deploy`.
*
* Use this for `schemaId` when calling any `client.agent.action`.
*
* It is generally recommended to call actions from the studio like this:
* ```ts
* await client.agent.action.generate({
* targetDocument: {
* operation: 'createIfNotExists',
* _id: props.documentIdForAction,
* _type: props.documentSchemaType.name,
* initialValues: props.getDocumentValue()
* },
* //...
* })
*
* ```
*/
schemaId: string;
/**
* This is the schema type of the field the actions will be attached to (ie, schemaType for `path`)
*
* It can be used with agent actions using `target.path`, to scope the action to a specific field.
*
* It is generally recommended to call actions from the studio like this:
* ```ts
* await client.agent.action.generate({
* targetDocument: {
* operation: 'createIfNotExists',
* _id: props.documentIdForAction,
* _type: props.documentSchemaType.name,
* initialValues: props.getDocumentValue()
* },
* target: {
* path: props.path
* },
* })
* ```
*/
path: AgentActionPath;
/**
* This is the schema type of the field the actions will be attached to (ie, schemaType for `path`).
*
* Typically useful to dynamically return different actions based on the schema type of the field.
*
* ```ts
* if(isObjectSchemaType(schemaType)) {
* return [
* defineAssistFieldAction({
* title: 'Fill the object fields',
* icon: RobotIcon,
* onAction: () => {
* //...
* }
* })
* ]
* }
* return useMemo(() => {
*
*
* }, [])
*
* ```
*/
schemaType: SchemaType;
/**
* Schema type of the parent field or array item holding this field.
*
* This can be undefined if the action was unable to resolve the parent type is excluded from AI Assist.
*
* @see schemaType
* @see documentSchemaType
*/
parentSchemaType?: SchemaType;
}
type AssistFieldActionNode = AssistFieldActionItem | AssistFieldActionGroup | DocumentFieldActionDivider;
type AssistFieldActionItem = Omit<DocumentFieldActionItem, 'renderAsButton' | 'selected' | 'onAction'> & {
onAction: () => void | Promise<void>;
};
type AssistFieldActionGroup = Omit<DocumentFieldActionGroup, 'renderAsButton' | 'expanded' | 'children'> & {
/**
* `children` can include undefined entries in the action array. These will be filtered out.
* If the group has no defined children, the group will also be filtered out.
*/
children: (AssistFieldActionNode | undefined)[];
};
declare function defineAssistFieldAction(action: Omit<AssistFieldActionItem, 'type'>): AssistFieldActionItem;
declare function defineFieldActionDivider(): DocumentFieldActionDivider;
declare function defineAssistFieldActionGroup(group: Omit<AssistFieldActionGroup, 'type'>): AssistFieldActionGroup;
interface Language {
id: string;
title?: string;
}
interface DocumentMember {
schemaType: SchemaType;
path: Path;
name: string;
value: unknown;
parentValue?: unknown;
}
interface TranslationOutput {
/** Language id */
id: string;
outputPath: Path;
}
type TranslationOutputsFunction = (documentMember: DocumentMember, enclosingType: SchemaType, translateFromLanguageId: string, translateToLanguageIds: string[]) => TranslationOutput[] | undefined;
type LanguageCallback = (client: SanityClient, selectedLanguageParams: Record<string, unknown>) => Promise<Language[]>;
interface FieldTranslationConfig {
/**
* `documentTypes` should be an array of strings where each entry must match a name from your document schemas.
*
* If defined, matching document will get a "Translate fields" instruction added.
**/
documentTypes?: string[];
/**
*
* Used for display strings in the Studio, and to determine languages for field level translations
*
* If the studio is using the sanity-plugin-internationalized-array plugin, this
* should be set to the same configuration.
*/
languages: Language[] | LanguageCallback;
/**
* API version for client passed to LanguageCallback for languages
* https://www.sanity.io/docs/api-versioning
* @defaultValue '2022-11-27'
*/
apiVersion?: string;
/**
* Specify fields that should be available in the languages callback:
* ```tsx
* {
* select: {
* markets: 'markets'
* },
* languages: (client, {markets}) =>
* client.fetch('*[_type == "language" && market in $markets]{id,title}', {markets})
* }
* ```
*
* If the studio is using the sanity-plugin-internationalized-array plugin, this
* should be set to the same configuration.
*/
selectLanguageParams?: Record<string, string>;
/**
* `translationOutputs` is used when the "Translate fields" instruction is started by a Studio user.
*
* It determines the relationships between document paths: Given a document path and a language, into which
* sibling paths should translations be output.
*
* `translationOutputs` is invoked once per path in the document (limited to a depth of 6), with the following:
*
* * `documentMember` - the field or array item for a given path; contains the path and its schemaType,
* * `enclosingType` - the schema type of parent holding the member
* * `translateFromLanguageId` - the languageId for the language the user want to translate from
* * `translateToLanguageIds` - all languageIds the user can translate to
*
* The function should return a `TranslationOutput[]` array that contains all the paths where translations from
* documentMember language (translateFromLanguageId) should be output.
*
* The function should return `undefined` for all documentMembers that should not be directly translated,
* or are nested fields under a translated path.
*
* ## Default function
*
* The default function for `translationOutputs` is configured to be automatically compatible with sanity-plugin-internationalized-array
* and object types prefixed with "locale".
*
* See <link to source for defaultTranslationOutputs> implementation details.
*
* ## Example
* A document has the following document members:
* * `{path: 'localeObject.en', schemaType: ObjectSchemaType}`
* * `{path: 'localeObject.en.title', schemaType: StringSchemaType}`
* * `{path: 'localeObject.de', schemaType: ObjectSchemaType}`,
* * `{path: 'localeObject.de.title', schemaType: StringSchemaType}`
*
* `translationOutputs` for invoked with `translateFromLanguageId` `en`,
* should only return [{id: 'de', outputPath: 'localeObject.de'}] for the `'localeObject.en'` path,
* and undefined for all the other members.
*
* ### Example implementation
* ```ts
* function translationOutputs(member, enclosingType, translateFromLanguageId, translateToLanguageIds)
* if (enclosingType.jsonType === 'object' && enclosingType.name.startsWith('locale') && translateFromLanguageId === member.name) {
* return translateToLanguageIds.map((translateToId) => ({
* id: translateToId,
* outputPath: [...member.path.slice(0, -1), translateToId],
* }))
* }
* return undefined
* }
* ```
*
* @see #maxPathDepth
**/
translationOutputs?: TranslationOutputsFunction;
/**
* The max depth for document paths AI Assist will translate.
*
* Depth is based on field path segments:
* - `title` has depth 1
* - `array[_key="no"].title` has depth 3
*
* Be careful not to set this too high in studios with recursive document schemas, as it could have
* negative impact on performance.
*
* Default: 6
*/
maxPathDepth?: number;
}
interface DocumentTranslationConfig {
/**
* Path to language field in documents. Can be a hidden field.
* For instance: 'config.language'
*
* For projects that use the `@sanity/document-internationalization` plugin,
* this should be the same as `languageField` config for that plugin.
*
* Default: 'language'
*/
languageField: string;
/**
* `documentTypes` should be an array of strings where each entry must match a name from your document schemas.
*
* If defined, this property will add a translate instruction to these document types.
* If undefined, the instruction will be added to all documents with aiAssistance enabled and a field matching `documentLanguageField` config.
*
* Documents with translation support will get a "Translate document>" instruction added.
**/
documentTypes?: string[];
}
interface TranslateStyleguideContext {
documentId: string;
schemaType: ObjectSchemaType;
client: SanityClient;
/**
* Only provided for field translations
*/
translatePath?: Path;
}
type TranslateStyleguide = string | ((context: TranslateStyleguideContext) => Promise<string>);
interface TranslationConfig {
/**
* Config for document types with fields in multiple languages in the same document.
*/
field?: FieldTranslationConfig;
/**
* Config for document types with a single language field that determines the language for the whole document.
*/
document?: DocumentTranslationConfig;
/**
* A "style guide" that can be used to provide guidance on how to translate content.
* Will be passed to the LLM - ergo this is only a guide and the model _may_ not
* always follow it to the letter.
*
* When providing a function, consider caching the results of any async operation; it will invoked every time translate runs
*/
styleguide?: TranslateStyleguide;
}
declare const userInputTypeName: "sanity.assist.instruction.userInput";
declare const instructionContextTypeName: "sanity.assist.instruction.context";
declare const fieldReferenceTypeName: "sanity.assist.instruction.fieldRef";
declare const contextDocumentTypeName: "assist.instruction.context";
declare const outputFieldTypeName: "sanity.assist.output.field";
declare const outputTypeTypeName: "sanity.assist.output.type";
interface PresetInstruction {
_key: string;
prompt?: PromptTextBlock[];
title?: string;
/**
* String key from `@sanity/icons` IconMap
*/
icon?: string;
/**
* Type/field filter
*/
output?: (OutputFieldItem | OutputTypeItem)[];
}
interface PresetField {
path?: string;
instructions?: PresetInstruction[];
}
interface AssistPreset {
fields?: PresetField[];
}
interface FieldRef extends PortableTextMarkDefinition {
_type: typeof fieldReferenceTypeName;
path?: string;
}
interface ContextBlock {
_type: typeof instructionContextTypeName;
reference?: {
_type: 'reference';
_ref?: string;
};
}
interface UserInputBlock {
_type: typeof userInputTypeName;
_key: string;
message?: string;
description?: string;
}
type InlinePromptBlock = PortableTextSpan | FieldRef | UserInputBlock | ContextBlock;
type PromptTextBlock = Omit<PortableTextBlock<never, InlinePromptBlock, 'normal', never>, '_type'> & {
_type: 'block';
};
interface OutputFieldItem {
_type: typeof outputFieldTypeName;
_key: string;
relativePath?: string;
}
interface OutputTypeItem {
_type: typeof outputTypeTypeName;
_key: string;
type?: string;
relativePath?: string;
}
interface AssistPluginConfig {
translate?: TranslationConfig;
/**
* Config that affects all instructions
*/
assist?: AssistConfig;
fieldActions?: {
title?: string;
/**
* The returned array can include `undefined` entries in the action array. These will be filtered out.
*/
useFieldActions?: (props: AssistFieldActionProps) => (AssistFieldActionNode | undefined)[];
};
/**
* @internal
*/
__customApiClient?: (defaultClient: SanityClient$1) => SanityClient$1;
/**
* @internal
*/
__presets?: Record<string, AssistPreset>;
}
declare const assist: _$sanity.Plugin<void | AssistPluginConfig>;
declare function SchemaTypeTool(): _$react_jsx_runtime0.JSX.Element;
interface AssistOptions {
aiAssist?: {
/** Set to true to disable assistance for this field or type */exclude?: boolean;
/**
* Set to true to add translation field-action to the field.
* Only has an effect in document types configured for document or field level translations.
*/
translateAction?: boolean;
};
}
declare module 'sanity' {
interface ArrayOptions extends AssistOptions {}
interface BlockOptions extends AssistOptions {}
interface BooleanOptions extends AssistOptions {}
interface CrossDatasetReferenceOptions extends AssistOptions {}
interface DateOptions extends AssistOptions {}
interface DatetimeOptions extends AssistOptions {}
interface DocumentOptions extends AssistOptions {}
interface FileOptions extends AssistOptions {}
interface GeopointOptions extends AssistOptions {}
interface ImageOptions {
aiAssist?: AssistOptions['aiAssist'] & {
/**
* When set, an image will be created whenever the `imageInstructionField` is written to by
* an AI Assist instruction.
*
* The value output by AI Assist will be use as an image prompt for an generative image AI.
*
* This means that instructions directly for the field or instructions that visit the field when running,
* will result in the image being changed.
*
* `imageInstructionField` must be a child-path relative to the image field, ie:
* * field
* * path.to.field
*
* ### Example
* ```ts
* defineType({
* type: 'image',
* name: 'articleImage',
* fields: [
* defineField({
* type: 'text',
* name: 'imagePrompt',
* title: 'Image prompt',
* rows: 2,
* }),
* ],
* options: {
* aiAssist: {
* imageInstructionField: 'imagePrompt',
* }
* },
* })
* ```
*/
imageInstructionField?: string;
/**
* When set, an image description will be automatically created for the image.
*
* `imageDescriptionField` must be a child-path relative to the image field, ie:
* * field
* * path.to.field
*
* Whenever the image asset for the field is changed in the Studio,
* an image description is generated and set into the `imageDescriptionField`.
*
* ### Example
* ```ts
* defineType({
* type: 'image',
* name: 'articleImage',
* fields: [
* defineField({
* type: 'string',
* name: 'altText',
* title: 'Alt text',
* }),
* ],
* options: {
* aiAssist: {
* imageDescriptionField: 'altText',
* }
* },
* })
* ```
*/
imageDescriptionField?: string | {
path: string;
/**
* When updateOnImageChange is true (or undefined), whenever the
* image asset changes, imageDescriptionField will be regenerated.
*
* default: true
* */
updateOnImageChange?: boolean;
};
};
}
interface NumberOptions extends AssistOptions {}
interface ObjectOptions extends AssistOptions {}
interface ReferenceBaseOptions {
aiAssist?: {
/** Set to true to disable assistance for this field or type */exclude?: boolean;
/**
* When set, the reference field will allow instructions to be added to it.
* Should be the name of the embeddings-index where assist will look for contextually relevant documents
* */
embeddingsIndex?: string;
};
}
interface SlugOptions extends AssistOptions {}
interface StringOptions extends AssistOptions {}
interface TextOptions extends AssistOptions {}
interface UrlOptions extends AssistOptions {}
interface EmailOptions extends AssistOptions {}
} //# sourceMappingURL=typeDefExtensions.d.ts.map
declare const defaultLanguageOutputs: TranslationOutputsFunction;
type GetUserInput = (args: {
/**
* Dialog title
*/
title: string;
/**
* One titled input per array item
*/
inputs: CustomInput[];
}) => Promise<CustomInputResult[] | undefined>;
/**
*
*/
interface CustomInput {
/**
* Id for the input
*/
id: string;
/**
* Title of the input field
*/
title: string;
/**
* Additional info that will be displayed over the input
*/
description?: string;
}
type CustomInputResult = {
/**
* Identifies which custom input the `result`belongs to
*/
input: CustomInput;
/**
* The text provided by the user in the input
*/
result: string;
};
/**
* `useUserInput` returns a function that can be used to await user input.
*
* Useful for custom `fieldActions` to get user input for populating Agent Action requests,.
*
* ```ts
* fieldActions: {
* useFieldActions: (props) => {
* const {
* documentSchemaType,
* schemaId,
* getDocumentValue,
* getConditionalPaths,
* documentIdForAction,
* } = props
* const client = useClient({apiVersion: 'vX'})
* const getUserInput = useUserInput()
* return useMemo(() => {
* return [
* defineAssistFieldAction({
* title: 'Log user input',
* icon: UserIcon,
* onAction: async () => {
* const input = await getUserInput({
* title: 'Topic',
* inputs: [{id: 'about', title: 'What should the article be about?'}],
* })
* if (!input) return // user canceled input
* await client.agent.action.generate({
* schemaId,
* targetDocument: {
* operation: 'createIfNotExists',
* _id: documentIdForAction,
* _type: documentSchemaType.name,
* initialValues: getDocumentValue(),
* },
* instruction: `
* Create a document about the following topic:
* $about
* ---
* `,
* instructionParams: {about: input[0].result},
* conditionalPaths: {paths: getConditionalPaths()},
* })
* },
* }),
* ]
* }, [
* client,
* documentSchemaType,
* schemaId,
* getDocumentValue,
* getConditionalPaths,
* documentIdForAction,
* getUserInput,
* ])
* },
* }
* ```
*/
declare function useUserInput(): GetUserInput;
/**
* Returns true if the `schemaType` or any of its parent types (`schemaType.type`)` has `name` equal
* to `typeName`.
*
* Useful for checking if `schemaType` is a type alias of `ìmage`, `code` or similar.
*/
declare function isType(schemaType: SchemaType, typeName: string): boolean;
export { AssistConfig, type AssistFieldActionGroup, type AssistFieldActionItem, type AssistFieldActionNode, type AssistFieldActionProps, AssistOptions, type CustomInput, type CustomInputResult, DocumentMember, DocumentTranslationConfig, FieldTranslationConfig, type GetUserInput, Language, LanguageCallback, LocaleSettings, LocaleSettingsContext, SchemaTypeTool, TranslateStyleguide, TranslateStyleguideContext, TranslationConfig, TranslationOutput, TranslationOutputsFunction, assist, contextDocumentTypeName, defaultLanguageOutputs, defineAssistFieldAction, defineAssistFieldActionGroup, defineFieldActionDivider, isType, useUserInput };
//# sourceMappingURL=index.d.ts.map