@sanity/client 6.28.2 → 6.28.3-instruct.0

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.
@@ -1,6 +1,7 @@
1
1
  import {lastValueFrom, Observable} from 'rxjs'
2
2
 
3
3
  import {AssetsClient, ObservableAssetsClient} from './assets/AssetsClient'
4
+ import {AssistClient, ObservableAssistClient} from './assist/AssistClient'
4
5
  import {defaultConfig, initConfig} from './config'
5
6
  import * as dataMethods from './data/dataMethods'
6
7
  import {_listen} from './data/listen'
@@ -65,7 +66,7 @@ export class ObservableSanityClient {
65
66
  live: LiveClient
66
67
  projects: ObservableProjectsClient
67
68
  users: ObservableUsersClient
68
-
69
+ assist: ObservableAssistClient
69
70
  /**
70
71
  * Private properties
71
72
  */
@@ -87,6 +88,7 @@ export class ObservableSanityClient {
87
88
  this.live = new LiveClient(this)
88
89
  this.projects = new ObservableProjectsClient(this, this.#httpRequest)
89
90
  this.users = new ObservableUsersClient(this, this.#httpRequest)
91
+ this.assist = new ObservableAssistClient(this, this.#httpRequest)
90
92
  }
91
93
 
92
94
  /**
@@ -733,6 +735,7 @@ export class SanityClient {
733
735
  live: LiveClient
734
736
  projects: ProjectsClient
735
737
  users: UsersClient
738
+ assist: AssistClient
736
739
 
737
740
  /**
738
741
  * Observable version of the Sanity client, with the same configuration as the promise-based one
@@ -760,6 +763,7 @@ export class SanityClient {
760
763
  this.live = new LiveClient(this)
761
764
  this.projects = new ProjectsClient(this, this.#httpRequest)
762
765
  this.users = new UsersClient(this, this.#httpRequest)
766
+ this.assist = new AssistClient(this, this.#httpRequest)
763
767
 
764
768
  this.observable = new ObservableSanityClient(httpRequest, config)
765
769
  }
@@ -0,0 +1,87 @@
1
+ import {lastValueFrom, type Observable} from 'rxjs'
2
+
3
+ import {_request} from '../data/dataMethods'
4
+ import type {ObservableSanityClient, SanityClient} from '../SanityClient'
5
+ import type {
6
+ Any,
7
+ AssistAsyncInstruction,
8
+ AssistInstruction,
9
+ AssistSyncInstruction,
10
+ HttpRequest,
11
+ IdentifiedSanityDocumentStub,
12
+ } from '../types'
13
+ import {hasDataset} from '../validators'
14
+
15
+ function _instruct<
16
+ DocumentShape extends Record<string, Any>,
17
+ Req extends AssistInstruction<DocumentShape>,
18
+ >(
19
+ client: SanityClient | ObservableSanityClient,
20
+ httpRequest: HttpRequest,
21
+ request: Req,
22
+ ): Observable<
23
+ Req['async'] extends true ? {_id: string} : IdentifiedSanityDocumentStub & DocumentShape
24
+ > {
25
+ const dataset = hasDataset(client.config())
26
+ return _request(client, httpRequest, {
27
+ method: 'POST',
28
+ uri: `/assist/tasks/instruct/${dataset}`,
29
+ body: request,
30
+ })
31
+ }
32
+
33
+ /** @public */
34
+ export class ObservableAssistClient {
35
+ #client: ObservableSanityClient
36
+ #httpRequest: HttpRequest
37
+ constructor(client: ObservableSanityClient, httpRequest: HttpRequest) {
38
+ this.#client = client
39
+ this.#httpRequest = httpRequest
40
+ }
41
+
42
+ instruct(request: AssistAsyncInstruction): Observable<{_id: string}>
43
+
44
+ instruct<DocumentShape extends Record<string, Any>>(
45
+ request: AssistSyncInstruction<DocumentShape>,
46
+ ): Observable<IdentifiedSanityDocumentStub & DocumentShape>
47
+
48
+ /**
49
+ * Run an ad-hoc instruction for a target document.
50
+ * @param request instruction request
51
+ */
52
+ instruct<DocumentShape extends Record<string, Any>, Req extends AssistInstruction<DocumentShape>>(
53
+ request: Req,
54
+ ): Observable<
55
+ Req['async'] extends true ? {_id: string} : IdentifiedSanityDocumentStub & DocumentShape
56
+ > {
57
+ return _instruct(this.#client, this.#httpRequest, request)
58
+ }
59
+ }
60
+
61
+ /** @public */
62
+ export class AssistClient {
63
+ #client: SanityClient
64
+ #httpRequest: HttpRequest
65
+ constructor(client: SanityClient, httpRequest: HttpRequest) {
66
+ this.#client = client
67
+ this.#httpRequest = httpRequest
68
+ }
69
+
70
+ instruct(request: AssistAsyncInstruction): Promise<{_id: string}>
71
+
72
+ instruct<DocumentShape extends Record<string, Any>>(
73
+ request: AssistSyncInstruction<DocumentShape>,
74
+ ): Promise<IdentifiedSanityDocumentStub & DocumentShape>
75
+
76
+ /**
77
+ * Run an ad-hoc instruction for a target document.
78
+ * @param request instruction request
79
+ */
80
+ instruct<DocumentShape extends Record<string, Any>, Req extends AssistInstruction<DocumentShape>>(
81
+ request: Req,
82
+ ): Promise<
83
+ Req['async'] extends true ? {_id: string} : IdentifiedSanityDocumentStub & DocumentShape
84
+ > {
85
+ return lastValueFrom(_instruct(this.#client, this.#httpRequest, request))
86
+ }
87
+ }
@@ -0,0 +1,203 @@
1
+ //Request shape
2
+
3
+ import type {Any, SanityDocumentStub} from '@sanity/client'
4
+
5
+ /** @beta */
6
+ export interface ConstantInstructionParam {
7
+ type: 'constant'
8
+ value: string
9
+ }
10
+
11
+ /**
12
+ *
13
+ * Includes a LLM-friendly version of the field value in the instruction
14
+ * @beta
15
+ * */
16
+ export interface FieldInstructionParam {
17
+ type: 'field'
18
+ /**
19
+ * Examples: 'title', 'array[_key=="key"].field
20
+ */
21
+ path: string
22
+ /**
23
+ * If omitted, implicitly uses the documentId of the instruction target
24
+ */
25
+ documentId?: string
26
+ }
27
+
28
+ /**
29
+ *
30
+ * Includes a LLM-friendly version of the document in the instruction
31
+ * @beta
32
+ * */
33
+ export interface DocumentInstructionParam {
34
+ type: 'document'
35
+ /**
36
+ * If omitted, implicitly uses the documentId of the instruction target
37
+ */
38
+ documentId?: string
39
+ }
40
+
41
+ /** @beta */
42
+ export interface GroqInstructionParam {
43
+ type: 'groq'
44
+ query: string
45
+ params?: Record<string, string>
46
+ }
47
+
48
+ /** @beta */
49
+ export type InstructionParam =
50
+ | string
51
+ | ConstantInstructionParam
52
+ | FieldInstructionParam
53
+ | DocumentInstructionParam
54
+ | GroqInstructionParam
55
+
56
+ /** @beta */
57
+ export type InstructionParams = Record<string, InstructionParam>
58
+
59
+ interface AssistRequestBase {
60
+ /** schemaId as reported by sanity deploy / sanity schema store */
61
+ schemaId: string
62
+ /** string template using $variable – more on this below under "Dynamic instruction" */
63
+ instruction: string
64
+ /** param values for the string template, keys are the variable name, ie if the template has "$variable", one key must be "variable" */
65
+ instructionParams?: InstructionParams
66
+ /**
67
+ * Optional document path output target for the instruction.
68
+ * When provided, the instruction will apply to this path in the document and its children.
69
+ *
70
+ * ## Examples
71
+ * - `path: 'title'` will output to the title field in the document
72
+ * - `path: 'array[_key="xx"]'` will output to the item with `_key: 'xx'` in the array field
73
+ */
74
+ path?: string
75
+
76
+ /**
77
+ * Controls sub-paths in the document that can be output to.
78
+ *
79
+ * The string-paths are relative to the `path` param
80
+ *
81
+ * Note: these path strings are less strictly validated than the `path` param itself:
82
+ * if an relative-path does not exist or is invalid, it will be silently ignored.
83
+ *
84
+ * @see AssistRequestBase#conditionalPaths
85
+ * @see AssistRequestBase#outputTypes
86
+ */
87
+ relativeOutputPaths?: {include: string[]} | {exclude: string[]}
88
+
89
+ /**
90
+ * Controls which types the instruction is allowed to output to.
91
+ *
92
+ * @see AssistRequestBase#relativeOutputPaths
93
+ * @see AssistRequestBase#conditionalPaths
94
+ */
95
+ outputTypes?: {include: string[]} | {exclude: string[]}
96
+
97
+ /**
98
+ * When a type or field in the schema has a function set for `hidden` or `readOnly`, it is conditional.
99
+ *
100
+ * By default, AI Assist will not output to conditional `readOnly` and `hidden` fields,
101
+ * ie, they are considered to resolve to `readOnly: true` / `hidden: true`.
102
+ *
103
+ * `conditionalPaths` param allows setting the default conditional value for
104
+ * `hidden` and `readOnly` to false,
105
+ * or individually set `hidden` and `readOnly` state for individual document paths.
106
+ *
107
+ *
108
+ * Note: fields and types with explicit readOnly: true or hidden: true in the schema, are not available to AI Assist,
109
+ * and cannot be changed via conditionalPaths.
110
+ *
111
+ * conditionalPaths state only apply to fields and types that have conditional `hidden` or `readOnly` in their schema definition.
112
+ *
113
+ * @see AssistRequestBase#relativeOutputPaths
114
+ * @see AssistRequestBase#outputTypes
115
+ */
116
+ conditionalPaths?: {
117
+ defaultReadOnly?: boolean
118
+ defaultHidden?: boolean
119
+ paths?: {
120
+ /** path here is not a relative path: it must be the full document path, regardless of `path` param on the request itself */
121
+ path: string
122
+ readOnly: boolean
123
+ hidden: boolean
124
+ }[]
125
+ }
126
+ }
127
+
128
+ interface Sync {
129
+ /**
130
+ * By default, skipWrite: false.
131
+ * Write enabled operations will mutate the target document, and emit AI presence in the studio.
132
+ *
133
+ * When skipWrite: true, the api will not mutate any documents nor emit presence.
134
+ * Ie, when true, no changes will be made to content-lake
135
+ *
136
+ * skipWrite: true is incompatible with async: true,
137
+ * as skipWrite implies that you will use the return value of the operation
138
+ */
139
+ skipWrite?: boolean
140
+
141
+ /**
142
+ * When async: true, requests responds with status 201 and {_id} as response body as soon as the request is validated.
143
+ * The instruction operation will carry on in the background.
144
+ *
145
+ * When async: false (default), requests respond with status 200 and the document value after instruction has been applied.
146
+ *
147
+ * async: true is incompatible with skipWrite: true, as async: true does not return the resulting document
148
+ */
149
+ async?: false
150
+ }
151
+
152
+ interface Async {
153
+ /**
154
+ * When async: true, requests responds with status 201 and {_id} as response body as soon as the request is validated.
155
+ * The instruction operation will carry on in the background.
156
+ *
157
+ * When async: false (default), requests respond with status 200 and the document value after instruction has been applied.
158
+ *
159
+ * async: true is incompatible with skipWrite, as async: true does not return the resulting document
160
+ */
161
+ async: true
162
+ }
163
+
164
+ /**
165
+ * Instruction for an existing document.
166
+ * @beta
167
+ */
168
+ interface ExistingDocumentRequest {
169
+ documentId: string
170
+ }
171
+
172
+ /**
173
+ * Instruction to create a new document
174
+ * @beta
175
+ */
176
+ interface CreateDocumentRequest<T extends Record<string, Any> = Record<string, Any>> {
177
+ createDocument: {
178
+ /** if no _id is provided, one will be generated. _id is always returned when the requests succeed */
179
+ _id?: string
180
+ _type: string
181
+ } & SanityDocumentStub<T>
182
+ }
183
+
184
+ /** @beta */
185
+ export type AssistSyncInstruction<T extends Record<string, Any> = Record<string, Any>> = (
186
+ | ExistingDocumentRequest
187
+ | CreateDocumentRequest<T>
188
+ ) &
189
+ AssistRequestBase &
190
+ Sync
191
+
192
+ /** @beta */
193
+ export type AssistAsyncInstruction<T extends Record<string, Any> = Record<string, Any>> = (
194
+ | ExistingDocumentRequest
195
+ | CreateDocumentRequest<T>
196
+ ) &
197
+ AssistRequestBase &
198
+ Async
199
+
200
+ /** @beta */
201
+ export type AssistInstruction<T extends Record<string, Any> = Record<string, Any>> =
202
+ | AssistSyncInstruction<T>
203
+ | AssistAsyncInstruction<T>
package/src/index.ts CHANGED
@@ -11,7 +11,7 @@ export const requester = exp.requester
11
11
 
12
12
  /**
13
13
  * @remarks
14
- * As of API version `v2025-02-19`, the default perspective used by the client has changed from `raw` to `published`. {@link https://www.sanity.io/changelog/e93a2d5a-9cee-4801-829e-8d3394bfed85|Changelog}
14
+ * As of API version `v2025-02-19`, the default perspective used by the client has changed from `raw` to `published`. {@link https://www.sanity.io/changelog/676aaa9d-2da6-44fb-abe5-580f28047c10|Changelog}
15
15
  * @public
16
16
  */
17
17
  export const createClient = exp.createClient
package/src/types.ts CHANGED
@@ -64,7 +64,7 @@ export interface ClientConfig {
64
64
  /**
65
65
  * What perspective to use for the client. See {@link https://www.sanity.io/docs/perspectives|perspective documentation}
66
66
  * @remarks
67
- * As of API version `v2025-02-19`, the default perspective has changed from `raw` to `published`. {@link https://www.sanity.io/changelog/e93a2d5a-9cee-4801-829e-8d3394bfed85|Changelog}
67
+ * As of API version `v2025-02-19`, the default perspective has changed from `raw` to `published`. {@link https://www.sanity.io/changelog/676aaa9d-2da6-44fb-abe5-580f28047c10|Changelog}
68
68
  * @defaultValue 'published'
69
69
  */
70
70
  perspective?: ClientPerspective
@@ -72,7 +72,7 @@ export interface ClientConfig {
72
72
 
73
73
  /**
74
74
  @remarks
75
- * As of API version `v2025-02-19`, the default perspective has changed from `raw` to `published`. {@link https://www.sanity.io/changelog/e93a2d5a-9cee-4801-829e-8d3394bfed85|Changelog}
75
+ * As of API version `v2025-02-19`, the default perspective has changed from `raw` to `published`. {@link https://www.sanity.io/changelog/676aaa9d-2da6-44fb-abe5-580f28047c10|Changelog}
76
76
  */
77
77
  apiVersion?: string
78
78
  proxy?: string
@@ -944,7 +944,7 @@ export interface ListenOptions {
944
944
 
945
945
  /**
946
946
  * Whether to include events for drafts and versions. As of API Version >= v2025-02-19, only events
947
- * for published documents will be included by default (see {@link https://www.sanity.io/changelog/e93a2d5a-9cee-4801-829e-8d3394bfed85|Changelog})
947
+ * for published documents will be included by default (see {@link https://www.sanity.io/changelog/676aaa9d-2da6-44fb-abe5-580f28047c10|Changelog})
948
948
  * If you need events from drafts and versions, set this to `true`.
949
949
  * Note: Keep in mind that additional document variants may be introduced in the future, so it's
950
950
  * recommended to respond to events in a way that's tolerant of potential future variants, e.g. by
@@ -1336,6 +1336,16 @@ export type ClientReturn<
1336
1336
  Fallback = Any,
1337
1337
  > = GroqString extends keyof SanityQueries ? SanityQueries[GroqString] : Fallback
1338
1338
 
1339
+ export type {
1340
+ AssistAsyncInstruction,
1341
+ AssistInstruction,
1342
+ AssistSyncInstruction,
1343
+ ConstantInstructionParam,
1344
+ FieldInstructionParam,
1345
+ GroqInstructionParam,
1346
+ InstructionParam,
1347
+ InstructionParams,
1348
+ } from './assist/types'
1339
1349
  export type {
1340
1350
  ContentSourceMapParsedPath,
1341
1351
  ContentSourceMapParsedPathKeyedSegment,
@@ -62,7 +62,10 @@ function _shareReplayLatest<T>(config: ShareReplayLatestConfig<T>): MonoTypeOper
62
62
  )
63
63
  const emitLatest = new Observable<T>((subscriber) => {
64
64
  if (emitted) {
65
- subscriber.next(latest)
65
+ subscriber.next(
66
+ // this cast is safe because of the emitted check which asserts that we got T from the source
67
+ latest as T,
68
+ )
66
69
  }
67
70
  subscriber.complete()
68
71
  })
@@ -2887,6 +2887,42 @@ ${selectionOpts}`);
2887
2887
  opts
2888
2888
  );
2889
2889
  }
2890
+ function _instruct(client, httpRequest, request) {
2891
+ const dataset2 = hasDataset(client.config());
2892
+ return _request(client, httpRequest, {
2893
+ method: "POST",
2894
+ uri: `/assist/tasks/instruct/${dataset2}`,
2895
+ body: request
2896
+ });
2897
+ }
2898
+ class ObservableAssistClient {
2899
+ #client;
2900
+ #httpRequest;
2901
+ constructor(client, httpRequest) {
2902
+ this.#client = client, this.#httpRequest = httpRequest;
2903
+ }
2904
+ /**
2905
+ * Run an ad-hoc instruction for a target document.
2906
+ * @param request instruction request
2907
+ */
2908
+ instruct(request) {
2909
+ return _instruct(this.#client, this.#httpRequest, request);
2910
+ }
2911
+ }
2912
+ class AssistClient {
2913
+ #client;
2914
+ #httpRequest;
2915
+ constructor(client, httpRequest) {
2916
+ this.#client = client, this.#httpRequest = httpRequest;
2917
+ }
2918
+ /**
2919
+ * Run an ad-hoc instruction for a target document.
2920
+ * @param request instruction request
2921
+ */
2922
+ instruct(request) {
2923
+ return lastValueFrom(_instruct(this.#client, this.#httpRequest, request));
2924
+ }
2925
+ }
2890
2926
  var defaults = (obj, defaults2) => Object.keys(defaults2).concat(Object.keys(obj)).reduce((target, prop) => (target[prop] = typeof obj[prop] > "u" ? defaults2[prop] : obj[prop], target), {});
2891
2927
  const pick = (obj, props) => props.reduce((selection, prop) => (typeof obj[prop] > "u" || (selection[prop] = obj[prop]), selection), {}), eventSourcePolyfill = defer(() => Promise.resolve().then(function () { return browser$1; })).pipe(
2892
2928
  map(({ default: EventSource2 }) => EventSource2),
@@ -2948,7 +2984,10 @@ ${selectionOpts}`);
2948
2984
  }),
2949
2985
  share(shareConfig)
2950
2986
  ), emitLatest = new Observable((subscriber) => {
2951
- emitted && subscriber.next(latest), subscriber.complete();
2987
+ emitted && subscriber.next(
2988
+ // this cast is safe because of the emitted check which asserts that we got T from the source
2989
+ latest
2990
+ ), subscriber.complete();
2952
2991
  });
2953
2992
  return merge(wrapped, emitLatest);
2954
2993
  };
@@ -3219,6 +3258,7 @@ ${selectionOpts}`);
3219
3258
  live;
3220
3259
  projects;
3221
3260
  users;
3261
+ assist;
3222
3262
  /**
3223
3263
  * Private properties
3224
3264
  */
@@ -3229,7 +3269,7 @@ ${selectionOpts}`);
3229
3269
  */
3230
3270
  listen = _listen;
3231
3271
  constructor(httpRequest, config = defaultConfig) {
3232
- this.config(config), this.#httpRequest = httpRequest, this.assets = new ObservableAssetsClient(this, this.#httpRequest), this.datasets = new ObservableDatasetsClient(this, this.#httpRequest), this.live = new LiveClient(this), this.projects = new ObservableProjectsClient(this, this.#httpRequest), this.users = new ObservableUsersClient(this, this.#httpRequest);
3272
+ this.config(config), this.#httpRequest = httpRequest, this.assets = new ObservableAssetsClient(this, this.#httpRequest), this.datasets = new ObservableDatasetsClient(this, this.#httpRequest), this.live = new LiveClient(this), this.projects = new ObservableProjectsClient(this, this.#httpRequest), this.users = new ObservableUsersClient(this, this.#httpRequest), this.assist = new ObservableAssistClient(this, this.#httpRequest);
3233
3273
  }
3234
3274
  /**
3235
3275
  * Clone the client - returns a new instance
@@ -3368,6 +3408,7 @@ ${selectionOpts}`);
3368
3408
  live;
3369
3409
  projects;
3370
3410
  users;
3411
+ assist;
3371
3412
  /**
3372
3413
  * Observable version of the Sanity client, with the same configuration as the promise-based one
3373
3414
  */
@@ -3382,7 +3423,7 @@ ${selectionOpts}`);
3382
3423
  */
3383
3424
  listen = _listen;
3384
3425
  constructor(httpRequest, config = defaultConfig) {
3385
- this.config(config), this.#httpRequest = httpRequest, this.assets = new AssetsClient(this, this.#httpRequest), this.datasets = new DatasetsClient(this, this.#httpRequest), this.live = new LiveClient(this), this.projects = new ProjectsClient(this, this.#httpRequest), this.users = new UsersClient(this, this.#httpRequest), this.observable = new ObservableSanityClient(httpRequest, config);
3426
+ this.config(config), this.#httpRequest = httpRequest, this.assets = new AssetsClient(this, this.#httpRequest), this.datasets = new DatasetsClient(this, this.#httpRequest), this.live = new LiveClient(this), this.projects = new ProjectsClient(this, this.#httpRequest), this.users = new UsersClient(this, this.#httpRequest), this.assist = new AssistClient(this, this.#httpRequest), this.observable = new ObservableSanityClient(httpRequest, config);
3386
3427
  }
3387
3428
  /**
3388
3429
  * Clone the client - returns a new instance