@sanity/client 8.2.0 → 8.4.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.
- package/README.md +2 -2
- package/dist/{browserUpload-2tz6Sdqp.js → browserUpload-C7PwCs-C.js} +6 -9
- package/dist/browserUpload-C7PwCs-C.js.map +1 -0
- package/dist/{browserUpload-CwpNx7Vl.js → browserUpload-D-2Rmfjo.js} +6 -9
- package/dist/browserUpload-D-2Rmfjo.js.map +1 -0
- package/dist/{config-3wiPP-sZ.js → config-CgJ16jET.js} +4 -2
- package/dist/config-CgJ16jET.js.map +1 -0
- package/dist/csm.js +1 -1
- package/dist/{dist-C9ExSk2R.js → dist-C5K_YcEU.js} +3 -2
- package/dist/{dist-C9ExSk2R.js.map → dist-C5K_YcEU.js.map} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +942 -115
- package/dist/index.js.map +1 -1
- package/dist/index.node.d.ts +3345 -16
- package/dist/index.node.js +865 -59
- package/dist/index.node.js.map +1 -1
- package/dist/media-library.d.ts +1 -1
- package/dist/rolldown-runtime-4YWMqDIC.js +9 -0
- package/dist/{stegaEncodeSourceMap-DbM2fTN4.js → stegaEncodeSourceMap-CO1HKnm2.js} +2 -2
- package/dist/{stegaEncodeSourceMap-DbM2fTN4.js.map → stegaEncodeSourceMap-CO1HKnm2.js.map} +1 -1
- package/dist/{types-nJhm5Nyq.d.ts → types-DiPF0ENT.d.ts} +3346 -17
- package/package.json +3 -3
- package/src/SanityClient.ts +7 -0
- package/src/assets/AssetsClient.ts +5 -0
- package/src/collaboration/types.ts +59 -8
- package/src/config.ts +1 -0
- package/src/context/ContextClient.ts +1006 -0
- package/src/context/openapi.json +5345 -0
- package/src/context/reads.ts +206 -0
- package/src/context/store.ts +100 -0
- package/src/context/types.gen.ts +2428 -0
- package/src/context/types.ts +228 -0
- package/src/data/dataMethods.ts +4 -1
- package/src/defineCreateClient.ts +1 -0
- package/src/functions/FunctionsClient.ts +52 -9
- package/src/functions/invoke.ts +47 -6
- package/src/http/browserUpload.ts +0 -12
- package/src/types.ts +29 -3
- package/src/util/createVersionId.ts +15 -5
- package/src/validators.ts +1 -0
- package/dist/browserUpload-2tz6Sdqp.js.map +0 -1
- package/dist/browserUpload-CwpNx7Vl.js.map +0 -1
- package/dist/config-3wiPP-sZ.js.map +0 -1
|
@@ -0,0 +1,1006 @@
|
|
|
1
|
+
import {type FetchFunction} from 'get-it'
|
|
2
|
+
import {lastValueFrom, type Observable} from 'rxjs'
|
|
3
|
+
|
|
4
|
+
import {_observe, _request} from '../data/dataMethods'
|
|
5
|
+
import type {ListenEventFromOptions} from '../data/listen'
|
|
6
|
+
import type {ObservableSanityClient, SanityClient} from '../SanityClient'
|
|
7
|
+
import type {HttpRequest, QueryParams, SanityDocument} from '../types'
|
|
8
|
+
import {
|
|
9
|
+
_listEntries,
|
|
10
|
+
_listInstructions,
|
|
11
|
+
_listIssues,
|
|
12
|
+
_listMcpEndpoints,
|
|
13
|
+
_readConversation,
|
|
14
|
+
_readEntry,
|
|
15
|
+
_readIssue,
|
|
16
|
+
_readMcpEndpoint,
|
|
17
|
+
} from './reads'
|
|
18
|
+
import {_fetch as _fetchStore, _listen as _listenStore} from './store'
|
|
19
|
+
import type {
|
|
20
|
+
ApplyIssuesParams,
|
|
21
|
+
ApplyIssuesResponse,
|
|
22
|
+
ClassifyConversationParams,
|
|
23
|
+
ContextListenOptions,
|
|
24
|
+
ContextRequestOptions,
|
|
25
|
+
Conversation,
|
|
26
|
+
ConversationDoc,
|
|
27
|
+
CreateFileImportParams,
|
|
28
|
+
CreateImportParams,
|
|
29
|
+
CreateInstructionParams,
|
|
30
|
+
CreateInstructionResponse,
|
|
31
|
+
CreateKnowledgeBaseParams,
|
|
32
|
+
DismissIssueResponse,
|
|
33
|
+
EditInstructionParams,
|
|
34
|
+
EditKnowledgeBaseParams,
|
|
35
|
+
Entry,
|
|
36
|
+
EntryDoc,
|
|
37
|
+
ImportDetail,
|
|
38
|
+
ImportDownloadResponse,
|
|
39
|
+
ImportsResponse,
|
|
40
|
+
Instruction,
|
|
41
|
+
InstructionDoc,
|
|
42
|
+
IssueDoc,
|
|
43
|
+
Job,
|
|
44
|
+
JobAccepted,
|
|
45
|
+
KnowledgeBase,
|
|
46
|
+
KnowledgeBasesResponse,
|
|
47
|
+
McpDoc,
|
|
48
|
+
RebuildEntryResponse,
|
|
49
|
+
ReopenIssueResponse,
|
|
50
|
+
RequestOptions,
|
|
51
|
+
ResolveIssueParams,
|
|
52
|
+
ResolveIssueResponse,
|
|
53
|
+
SaveConversationParams,
|
|
54
|
+
Source,
|
|
55
|
+
SourceContentResponse,
|
|
56
|
+
SourceDetail,
|
|
57
|
+
SourcesResponse,
|
|
58
|
+
StagedUpload,
|
|
59
|
+
} from './types'
|
|
60
|
+
|
|
61
|
+
type ListOptions = RequestOptions & {cursor?: string; limit?: number}
|
|
62
|
+
|
|
63
|
+
type Client = SanityClient | ObservableSanityClient
|
|
64
|
+
|
|
65
|
+
const COLLECTION_URL = '/context/knowledge-bases'
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The knowledge base every scoped method operates on comes from the client's
|
|
69
|
+
* `resource` configuration, matching how media libraries and canvases are
|
|
70
|
+
* addressed. Resolved per call so `withConfig` clones behave.
|
|
71
|
+
*/
|
|
72
|
+
function _resolveKnowledgeBaseId(client: Client): string {
|
|
73
|
+
const resource = client.config().resource
|
|
74
|
+
|
|
75
|
+
if (resource?.type !== 'knowledge-base') {
|
|
76
|
+
throw new Error(
|
|
77
|
+
'`resource` of type `knowledge-base` must be configured to use knowledge-base methods',
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return resource.id
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function _knowledgeBaseUrl(knowledgeBaseId: string, suffix = ''): string {
|
|
85
|
+
return `${COLLECTION_URL}/${encodeURIComponent(knowledgeBaseId)}${suffix}`
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Serialize defined values into query params, dropping the undefined ones. */
|
|
89
|
+
function _conversationUrl(client: Client, threadId: string): string {
|
|
90
|
+
const organizationId = client.config().context?.organizationId
|
|
91
|
+
|
|
92
|
+
if (!organizationId) {
|
|
93
|
+
throw new Error('`context.organizationId` must be configured to record conversations')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!threadId) {
|
|
97
|
+
throw new Error('`threadId` must be provided')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return `/context/organizations/${encodeURIComponent(organizationId)}/conversations/${encodeURIComponent(threadId)}`
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function _query(entries: Record<string, string | number | undefined>): Record<string, string> {
|
|
104
|
+
return Object.fromEntries(
|
|
105
|
+
Object.entries(entries).flatMap(([key, value]) =>
|
|
106
|
+
value === undefined ? [] : [[key, `${value}`]],
|
|
107
|
+
),
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function _fetchBody(file: CreateFileImportParams['file']) {
|
|
112
|
+
if (!ArrayBuffer.isView(file)) return file
|
|
113
|
+
return file.buffer instanceof ArrayBuffer
|
|
114
|
+
? new Uint8Array(file.buffer, file.byteOffset, file.byteLength)
|
|
115
|
+
: Uint8Array.from(file)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* `client.context` — knowledge bases and everything scoped to them.
|
|
120
|
+
*
|
|
121
|
+
* Collection-level management (create, list, get, edit, delete) addresses
|
|
122
|
+
* knowledge bases per call, like `client.projects`. Everything scoped to one
|
|
123
|
+
* knowledge base (imports, builds, issues, entries, ...) operates on the
|
|
124
|
+
* client's configured `resource`, like media libraries:
|
|
125
|
+
*
|
|
126
|
+
* @example Full lifecycle
|
|
127
|
+
* ```ts
|
|
128
|
+
* const created = await client.context.knowledgeBases.create({
|
|
129
|
+
* organizationId: 'org123',
|
|
130
|
+
* title: 'Support docs',
|
|
131
|
+
* description: 'Product docs and troubleshooting guides',
|
|
132
|
+
* })
|
|
133
|
+
*
|
|
134
|
+
* const kb = createClient({
|
|
135
|
+
* apiVersion: '2026-08-25',
|
|
136
|
+
* token,
|
|
137
|
+
* resource: {type: 'knowledge-base', id: created.publicId},
|
|
138
|
+
* })
|
|
139
|
+
*
|
|
140
|
+
* await kb.context.imports.create({type: 'text', title: 'Refund policy', content: refundMd})
|
|
141
|
+
* const {jobId} = await kb.context.build()
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @beta
|
|
145
|
+
*/
|
|
146
|
+
export class ContextClient {
|
|
147
|
+
#client: SanityClient
|
|
148
|
+
#httpRequest: HttpRequest
|
|
149
|
+
|
|
150
|
+
constructor(client: SanityClient, httpRequest: HttpRequest) {
|
|
151
|
+
this.#client = client
|
|
152
|
+
this.#httpRequest = httpRequest
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Request against the configured knowledge base. */
|
|
156
|
+
#request<R>(
|
|
157
|
+
suffix: string,
|
|
158
|
+
reqOptions: {
|
|
159
|
+
method?: string
|
|
160
|
+
body?: unknown
|
|
161
|
+
query?: Record<string, string>
|
|
162
|
+
} & RequestOptions = {},
|
|
163
|
+
): Promise<R> {
|
|
164
|
+
return _request<R>(this.#client, this.#httpRequest, {
|
|
165
|
+
url: _knowledgeBaseUrl(_resolveKnowledgeBaseId(this.#client), suffix),
|
|
166
|
+
...reqOptions,
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Shared shape of every paginated list endpoint scoped to the knowledge base. */
|
|
171
|
+
#list<R>(
|
|
172
|
+
suffix: string,
|
|
173
|
+
params?: ListOptions,
|
|
174
|
+
extraQuery?: Record<string, string | undefined>,
|
|
175
|
+
): Promise<R> {
|
|
176
|
+
return this.#request<R>(suffix, {
|
|
177
|
+
query: _query({
|
|
178
|
+
cursor: params?.cursor,
|
|
179
|
+
limit: params?.limit,
|
|
180
|
+
...extraQuery,
|
|
181
|
+
}),
|
|
182
|
+
signal: params?.signal,
|
|
183
|
+
tag: params?.tag,
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async #uploadFile(
|
|
188
|
+
params: CreateFileImportParams,
|
|
189
|
+
options?: RequestOptions,
|
|
190
|
+
): Promise<JobAccepted> {
|
|
191
|
+
const staged = await this.#request<StagedUpload>('/imports/uploads', {
|
|
192
|
+
method: 'POST',
|
|
193
|
+
body: {
|
|
194
|
+
filename: params.filename,
|
|
195
|
+
...(params.contentType && {contentType: params.contentType}),
|
|
196
|
+
},
|
|
197
|
+
...options,
|
|
198
|
+
})
|
|
199
|
+
// The signed URL PUT goes straight to storage, outside the API pipeline:
|
|
200
|
+
// no auth header, and the body is raw bytes rather than JSON. Still uses
|
|
201
|
+
// the client's fetch resolution so proxy config applies in Node.
|
|
202
|
+
const config = this.#client.config()
|
|
203
|
+
const doFetch: FetchFunction = config.resolveFetch?.(config.proxy) ?? globalThis.fetch
|
|
204
|
+
const putResponse = await doFetch(staged.uploadUrl, {
|
|
205
|
+
method: 'PUT',
|
|
206
|
+
body: _fetchBody(params.file),
|
|
207
|
+
...(params.contentType && {
|
|
208
|
+
headers: {'content-type': params.contentType},
|
|
209
|
+
}),
|
|
210
|
+
signal: options?.signal,
|
|
211
|
+
})
|
|
212
|
+
if (!putResponse.ok) {
|
|
213
|
+
throw new Error(`File upload failed: ${putResponse.status} ${putResponse.statusText}`)
|
|
214
|
+
}
|
|
215
|
+
return this.#request<JobAccepted>(
|
|
216
|
+
`/imports/uploads/${encodeURIComponent(staged.importId)}/complete`,
|
|
217
|
+
{
|
|
218
|
+
method: 'POST',
|
|
219
|
+
body: {},
|
|
220
|
+
...options,
|
|
221
|
+
},
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** The knowledge base collection: management addressed per call. */
|
|
226
|
+
knowledgeBases = {
|
|
227
|
+
/** Create a knowledge base. Requires the org-level knowledge-base create grant. */
|
|
228
|
+
create: (params: CreateKnowledgeBaseParams, options?: RequestOptions): Promise<KnowledgeBase> =>
|
|
229
|
+
_request<KnowledgeBase>(this.#client, this.#httpRequest, {
|
|
230
|
+
url: COLLECTION_URL,
|
|
231
|
+
method: 'POST',
|
|
232
|
+
body: params,
|
|
233
|
+
...options,
|
|
234
|
+
}),
|
|
235
|
+
/** List the organization's knowledge bases. */
|
|
236
|
+
list: (params: {organizationId: string} & ListOptions): Promise<KnowledgeBasesResponse> =>
|
|
237
|
+
_request<KnowledgeBasesResponse>(this.#client, this.#httpRequest, {
|
|
238
|
+
url: COLLECTION_URL,
|
|
239
|
+
query: _query({
|
|
240
|
+
organizationId: params.organizationId,
|
|
241
|
+
cursor: params.cursor,
|
|
242
|
+
limit: params.limit,
|
|
243
|
+
}),
|
|
244
|
+
signal: params.signal,
|
|
245
|
+
tag: params.tag,
|
|
246
|
+
}),
|
|
247
|
+
/** Fetch a knowledge base by its id. */
|
|
248
|
+
get: (knowledgeBaseId: string, options?: RequestOptions): Promise<KnowledgeBase> =>
|
|
249
|
+
_request<KnowledgeBase>(this.#client, this.#httpRequest, {
|
|
250
|
+
url: _knowledgeBaseUrl(knowledgeBaseId),
|
|
251
|
+
...options,
|
|
252
|
+
}),
|
|
253
|
+
/** Edit a knowledge base's configuration. */
|
|
254
|
+
edit: (
|
|
255
|
+
knowledgeBaseId: string,
|
|
256
|
+
params: EditKnowledgeBaseParams,
|
|
257
|
+
options?: RequestOptions,
|
|
258
|
+
): Promise<KnowledgeBase> =>
|
|
259
|
+
_request<KnowledgeBase>(this.#client, this.#httpRequest, {
|
|
260
|
+
url: _knowledgeBaseUrl(knowledgeBaseId),
|
|
261
|
+
method: 'PATCH',
|
|
262
|
+
body: params,
|
|
263
|
+
...options,
|
|
264
|
+
}),
|
|
265
|
+
/** Delete a knowledge base and its generated content. */
|
|
266
|
+
delete: async (knowledgeBaseId: string, options?: RequestOptions): Promise<void> => {
|
|
267
|
+
await _request<void>(this.#client, this.#httpRequest, {
|
|
268
|
+
url: _knowledgeBaseUrl(knowledgeBaseId),
|
|
269
|
+
method: 'DELETE',
|
|
270
|
+
...options,
|
|
271
|
+
})
|
|
272
|
+
},
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* GROQ over the organization's Context documents (conversation telemetry
|
|
277
|
+
* today; the store holds every Context family and the caller's access
|
|
278
|
+
* decides what a query returns, so filter on `_type`).
|
|
279
|
+
*
|
|
280
|
+
* Requires `context.organizationId` in the client configuration.
|
|
281
|
+
*/
|
|
282
|
+
fetch<R = unknown>(
|
|
283
|
+
query: string,
|
|
284
|
+
params?: QueryParams,
|
|
285
|
+
options?: ContextRequestOptions,
|
|
286
|
+
): Promise<R> {
|
|
287
|
+
return lastValueFrom(_fetchStore<R>(this.#client, this.#httpRequest, query, params, options))
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Listen for changes to the organization's Context documents. Mirrors
|
|
292
|
+
* `client.listen(query, params, options)` and emits mutation events by
|
|
293
|
+
* default.
|
|
294
|
+
*/
|
|
295
|
+
listen<Opts extends ContextListenOptions | undefined = undefined>(
|
|
296
|
+
query: string,
|
|
297
|
+
params?: QueryParams,
|
|
298
|
+
options?: Opts,
|
|
299
|
+
): Observable<ListenEventFromOptions<SanityDocument, Opts>> {
|
|
300
|
+
return _listenStore(this.#client, query, params, options)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Conversation telemetry. `threadId` identifies the conversation within
|
|
305
|
+
* the organization — reuse means the same conversation. Beyond the canned
|
|
306
|
+
* `get`, reads go through {@link fetch} and {@link listen} with GROQ
|
|
307
|
+
* (`_type == "sanity.context.conversation"`).
|
|
308
|
+
*
|
|
309
|
+
* Requires `context.organizationId` in the client configuration.
|
|
310
|
+
*/
|
|
311
|
+
conversations = {
|
|
312
|
+
/**
|
|
313
|
+
* Record a conversation. Messages replace the stored transcript
|
|
314
|
+
* wholesale; `metadata` and model fields only overwrite when present.
|
|
315
|
+
* Last write per thread wins — retries are safe.
|
|
316
|
+
*/
|
|
317
|
+
save: (
|
|
318
|
+
params: {threadId: string} & SaveConversationParams,
|
|
319
|
+
options?: RequestOptions,
|
|
320
|
+
): Promise<Conversation> => {
|
|
321
|
+
const {threadId, ...body} = params
|
|
322
|
+
return _request<Conversation>(this.#client, this.#httpRequest, {
|
|
323
|
+
url: _conversationUrl(this.#client, threadId),
|
|
324
|
+
method: 'PUT',
|
|
325
|
+
body,
|
|
326
|
+
...options,
|
|
327
|
+
})
|
|
328
|
+
},
|
|
329
|
+
/**
|
|
330
|
+
* Record the classification your own model produced for one thread:
|
|
331
|
+
* exactly one of `coreMetrics` (a verdict) or `classificationError`
|
|
332
|
+
* (why classification failed).
|
|
333
|
+
*/
|
|
334
|
+
classify: (
|
|
335
|
+
params: {threadId: string} & ClassifyConversationParams,
|
|
336
|
+
options?: RequestOptions,
|
|
337
|
+
): Promise<Conversation> => {
|
|
338
|
+
const {threadId, ...body} = params
|
|
339
|
+
return _request<Conversation>(this.#client, this.#httpRequest, {
|
|
340
|
+
url: _conversationUrl(this.#client, threadId),
|
|
341
|
+
method: 'PATCH',
|
|
342
|
+
body,
|
|
343
|
+
...options,
|
|
344
|
+
})
|
|
345
|
+
},
|
|
346
|
+
/**
|
|
347
|
+
* One recorded conversation by its thread id, or `null` when the thread
|
|
348
|
+
* was never recorded. Runs:
|
|
349
|
+
*
|
|
350
|
+
* `*[_type == "sanity.context.conversation" && organizationId == $org && threadId == $threadId][0]`
|
|
351
|
+
*
|
|
352
|
+
* For anything more, use {@link fetch}.
|
|
353
|
+
*/
|
|
354
|
+
get: (
|
|
355
|
+
params: {threadId: string},
|
|
356
|
+
options?: ContextRequestOptions,
|
|
357
|
+
): Promise<ConversationDoc | null> =>
|
|
358
|
+
_readConversation(this.#client, this.#httpRequest, params.threadId, options),
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Build the configured knowledge base. The server waits for pending import
|
|
363
|
+
* processing before assembling, so importing and building back to back is
|
|
364
|
+
* safe. Track the returned job with {@link jobs}.
|
|
365
|
+
*/
|
|
366
|
+
build(options?: RequestOptions): Promise<JobAccepted> {
|
|
367
|
+
return this.#request('/build', {method: 'POST', ...options})
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Cancel the running build, if any. */
|
|
371
|
+
cancelBuild(options?: RequestOptions): Promise<{cancelled: boolean}> {
|
|
372
|
+
return this.#request('/build/cancel', {method: 'POST', ...options})
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** Run an incremental refresh: re-check sources and apply what changed. */
|
|
376
|
+
refresh(options?: RequestOptions): Promise<{jobId: string; started: boolean}> {
|
|
377
|
+
return this.#request('/refresh', {method: 'POST', ...options})
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** Imports: feed content into the configured knowledge base. */
|
|
381
|
+
imports = {
|
|
382
|
+
/**
|
|
383
|
+
* Import content. One entry point, discriminated on `type`: inline
|
|
384
|
+
* `text`, a website `crawl`, a Sanity `dataset` bind, or a `file`
|
|
385
|
+
* upload. Processing queues automatically. The file variant stages the
|
|
386
|
+
* upload, PUTs the bytes to a signed storage URL, and confirms; the
|
|
387
|
+
* bytes never pass through the Context API.
|
|
388
|
+
*/
|
|
389
|
+
create: (
|
|
390
|
+
params: CreateImportParams | CreateFileImportParams,
|
|
391
|
+
options?: RequestOptions,
|
|
392
|
+
): Promise<JobAccepted> =>
|
|
393
|
+
params.type === 'file'
|
|
394
|
+
? this.#uploadFile(params, options)
|
|
395
|
+
: this.#request('/imports', {
|
|
396
|
+
method: 'POST',
|
|
397
|
+
body: params,
|
|
398
|
+
...options,
|
|
399
|
+
}),
|
|
400
|
+
list: (params?: ListOptions) => this.#list<ImportsResponse>('/imports', params),
|
|
401
|
+
get: (params: {importId: string}, options?: RequestOptions) =>
|
|
402
|
+
this.#request<ImportDetail>(`/imports/${encodeURIComponent(params.importId)}`, options),
|
|
403
|
+
/** A short-lived signed URL for the original uploaded bytes. */
|
|
404
|
+
download: (params: {importId: string}, options?: RequestOptions) =>
|
|
405
|
+
this.#request<ImportDownloadResponse>(
|
|
406
|
+
`/imports/${encodeURIComponent(params.importId)}/download`,
|
|
407
|
+
options,
|
|
408
|
+
),
|
|
409
|
+
delete: async (params: {importId: string}, options?: RequestOptions) => {
|
|
410
|
+
await this.#request<void>(`/imports/${encodeURIComponent(params.importId)}`, {
|
|
411
|
+
method: 'DELETE',
|
|
412
|
+
...options,
|
|
413
|
+
})
|
|
414
|
+
},
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** Jobs: poll async work (builds, imports) to a terminal state. */
|
|
418
|
+
jobs = {
|
|
419
|
+
get: (params: {jobId: string}, options?: RequestOptions) =>
|
|
420
|
+
this.#request<Job>(`/jobs/${encodeURIComponent(params.jobId)}`, options),
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Issues: findings from builds awaiting triage. Reads are canned GROQ
|
|
425
|
+
* queries against the organization's document store; for anything more,
|
|
426
|
+
* use {@link fetch}. Reads require `context.organizationId` alongside the
|
|
427
|
+
* knowledge-base `resource` in the client configuration.
|
|
428
|
+
*/
|
|
429
|
+
issues = {
|
|
430
|
+
/**
|
|
431
|
+
* Every issue on the knowledge base, oldest first, optionally narrowed
|
|
432
|
+
* to one status. Drains keyset pages internally and resolves with the
|
|
433
|
+
* complete set. Runs:
|
|
434
|
+
*
|
|
435
|
+
* `*[_type == "sanity.context.issue" && knowledgeBaseId == $kb && status == $status] | order(_createdAt asc, _id asc)`
|
|
436
|
+
*
|
|
437
|
+
* (the status clause only when given). For anything more, use {@link fetch}.
|
|
438
|
+
*/
|
|
439
|
+
list: (
|
|
440
|
+
params?: {status?: 'open' | 'accepted' | 'rejected'},
|
|
441
|
+
options?: ContextRequestOptions,
|
|
442
|
+
): Promise<IssueDoc[]> =>
|
|
443
|
+
_listIssues(
|
|
444
|
+
this.#client,
|
|
445
|
+
this.#httpRequest,
|
|
446
|
+
_resolveKnowledgeBaseId(this.#client),
|
|
447
|
+
params?.status,
|
|
448
|
+
options,
|
|
449
|
+
),
|
|
450
|
+
/**
|
|
451
|
+
* One issue by its document id, or `null` when it does not exist. Runs:
|
|
452
|
+
*
|
|
453
|
+
* `*[_type == "sanity.context.issue" && knowledgeBaseId == $kb && _id == $id][0]`
|
|
454
|
+
*
|
|
455
|
+
* For anything more, use {@link fetch}.
|
|
456
|
+
*/
|
|
457
|
+
get: (params: {issueId: string}, options?: ContextRequestOptions): Promise<IssueDoc | null> =>
|
|
458
|
+
_readIssue(
|
|
459
|
+
this.#client,
|
|
460
|
+
this.#httpRequest,
|
|
461
|
+
_resolveKnowledgeBaseId(this.#client),
|
|
462
|
+
params.issueId,
|
|
463
|
+
options,
|
|
464
|
+
),
|
|
465
|
+
/** Resolve a conflict issue. Mints the standing instruction, same as the dashboard. */
|
|
466
|
+
resolve: (params: {issueId: string} & ResolveIssueParams, options?: RequestOptions) => {
|
|
467
|
+
const {issueId, ...body} = params
|
|
468
|
+
return this.#request<ResolveIssueResponse>(`/issues/${encodeURIComponent(issueId)}/resolve`, {
|
|
469
|
+
method: 'POST',
|
|
470
|
+
body,
|
|
471
|
+
...options,
|
|
472
|
+
})
|
|
473
|
+
},
|
|
474
|
+
dismiss: (params: {issueId: string}, options?: RequestOptions) =>
|
|
475
|
+
this.#request<DismissIssueResponse>(`/issues/${encodeURIComponent(params.issueId)}/dismiss`, {
|
|
476
|
+
method: 'POST',
|
|
477
|
+
...options,
|
|
478
|
+
}),
|
|
479
|
+
reopen: (params: {issueId: string}, options?: RequestOptions) =>
|
|
480
|
+
this.#request<ReopenIssueResponse>(`/issues/${encodeURIComponent(params.issueId)}/reopen`, {
|
|
481
|
+
method: 'POST',
|
|
482
|
+
...options,
|
|
483
|
+
}),
|
|
484
|
+
/** Apply already-accepted issues to the knowledge base in one batch. */
|
|
485
|
+
apply: (params: ApplyIssuesParams, options?: RequestOptions) =>
|
|
486
|
+
this.#request<ApplyIssuesResponse>('/issues/apply', {
|
|
487
|
+
method: 'POST',
|
|
488
|
+
body: params,
|
|
489
|
+
...options,
|
|
490
|
+
}),
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/** Instructions: standing decisions that steer every build. */
|
|
494
|
+
instructions = {
|
|
495
|
+
create: (
|
|
496
|
+
params: CreateInstructionParams,
|
|
497
|
+
options?: RequestOptions,
|
|
498
|
+
): Promise<CreateInstructionResponse> =>
|
|
499
|
+
this.#request<CreateInstructionResponse>('/instructions', {
|
|
500
|
+
method: 'POST',
|
|
501
|
+
body: params,
|
|
502
|
+
...options,
|
|
503
|
+
}),
|
|
504
|
+
/**
|
|
505
|
+
* Every current-schema instruction on the knowledge base, oldest first.
|
|
506
|
+
* Drains keyset pages internally and resolves with the complete set.
|
|
507
|
+
* Runs:
|
|
508
|
+
*
|
|
509
|
+
* `*[_type == "sanity.context.instruction" && knowledgeBaseId == $kb && schemaVersion == 1] | order(_createdAt asc, _id asc)`
|
|
510
|
+
*
|
|
511
|
+
* For anything more, use {@link fetch}. Requires `context.organizationId`
|
|
512
|
+
* alongside the knowledge-base `resource` in the client configuration.
|
|
513
|
+
*/
|
|
514
|
+
list: (options?: ContextRequestOptions): Promise<InstructionDoc[]> =>
|
|
515
|
+
_listInstructions(
|
|
516
|
+
this.#client,
|
|
517
|
+
this.#httpRequest,
|
|
518
|
+
_resolveKnowledgeBaseId(this.#client),
|
|
519
|
+
options,
|
|
520
|
+
),
|
|
521
|
+
edit: (params: {instructionId: string} & EditInstructionParams, options?: RequestOptions) => {
|
|
522
|
+
const {instructionId, ...body} = params
|
|
523
|
+
return this.#request<Instruction>(`/instructions/${encodeURIComponent(instructionId)}`, {
|
|
524
|
+
method: 'PATCH',
|
|
525
|
+
body,
|
|
526
|
+
...options,
|
|
527
|
+
})
|
|
528
|
+
},
|
|
529
|
+
delete: async (params: {instructionId: string}, options?: RequestOptions) => {
|
|
530
|
+
await this.#request<void>(`/instructions/${encodeURIComponent(params.instructionId)}`, {
|
|
531
|
+
method: 'DELETE',
|
|
532
|
+
...options,
|
|
533
|
+
})
|
|
534
|
+
},
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Entries: the built outline, one entry per node. Reads are canned GROQ
|
|
539
|
+
* queries against the organization's document store; for anything more,
|
|
540
|
+
* use {@link fetch}. Requires `context.organizationId` alongside the
|
|
541
|
+
* knowledge-base `resource` in the client configuration.
|
|
542
|
+
*/
|
|
543
|
+
entries = {
|
|
544
|
+
/**
|
|
545
|
+
* Every entry, path-ordered, as a metadata view (`_id`, `path`,
|
|
546
|
+
* `title`, `tldr`, `status`) with bodies excluded. Drains keyset pages
|
|
547
|
+
* internally and resolves with the complete set. Runs:
|
|
548
|
+
*
|
|
549
|
+
* `*[_type == "sanity.context.entry" && knowledgeBaseId == $kb && path > $after] | order(path asc) [0...200] {_id, path, title, tldr, status}`
|
|
550
|
+
*
|
|
551
|
+
* For bodies, use `entries.get` or {@link fetch}.
|
|
552
|
+
*/
|
|
553
|
+
list: (options?: ContextRequestOptions): Promise<Entry[]> =>
|
|
554
|
+
_listEntries(this.#client, this.#httpRequest, _resolveKnowledgeBaseId(this.#client), options),
|
|
555
|
+
/**
|
|
556
|
+
* One entry with its full body and citations, by outline path (e.g.
|
|
557
|
+
* `billing/refunds`), or `null` when no entry sits at that path. Runs:
|
|
558
|
+
*
|
|
559
|
+
* `*[_type == "sanity.context.entry" && knowledgeBaseId == $kb && path == $path][0]`
|
|
560
|
+
*
|
|
561
|
+
* For anything more, use {@link fetch}.
|
|
562
|
+
*/
|
|
563
|
+
get: (params: {path: string}, options?: ContextRequestOptions): Promise<EntryDoc | null> =>
|
|
564
|
+
_readEntry(
|
|
565
|
+
this.#client,
|
|
566
|
+
this.#httpRequest,
|
|
567
|
+
_resolveKnowledgeBaseId(this.#client),
|
|
568
|
+
params.path,
|
|
569
|
+
options,
|
|
570
|
+
),
|
|
571
|
+
/**
|
|
572
|
+
* Rebuild one entry from its already-placed sources, by outline path.
|
|
573
|
+
* Poll the returned job with {@link jobs}; `affectedEntries` lists every
|
|
574
|
+
* entry the rebuild touches.
|
|
575
|
+
*/
|
|
576
|
+
rebuild: (params: {path: string}, options?: RequestOptions): Promise<RebuildEntryResponse> =>
|
|
577
|
+
this.#request<RebuildEntryResponse>(`/entries/${encodeURIComponent(params.path)}/rebuild`, {
|
|
578
|
+
method: 'POST',
|
|
579
|
+
...options,
|
|
580
|
+
}),
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* MCP endpoint configurations, org-owned documents read with canned GROQ
|
|
585
|
+
* queries. Requires `context.organizationId` in the client configuration.
|
|
586
|
+
*/
|
|
587
|
+
mcpEndpoints = {
|
|
588
|
+
/**
|
|
589
|
+
* The organization's MCP endpoint configurations, oldest first. Runs:
|
|
590
|
+
*
|
|
591
|
+
* `*[_type == "sanity.context.mcp" && organizationId == $org] | order(_createdAt asc, _id asc) [0...500]`
|
|
592
|
+
*
|
|
593
|
+
* For anything more, use {@link fetch}.
|
|
594
|
+
*/
|
|
595
|
+
list: (options?: ContextRequestOptions): Promise<McpDoc[]> =>
|
|
596
|
+
_listMcpEndpoints(this.#client, this.#httpRequest, options),
|
|
597
|
+
/**
|
|
598
|
+
* One MCP endpoint configuration by its URL name, or `null` when none
|
|
599
|
+
* carries that name. Runs:
|
|
600
|
+
*
|
|
601
|
+
* `*[_type == "sanity.context.mcp" && organizationId == $org && name == $name][0]`
|
|
602
|
+
*
|
|
603
|
+
* For anything more, use {@link fetch}.
|
|
604
|
+
*/
|
|
605
|
+
get: (params: {name: string}, options?: ContextRequestOptions): Promise<McpDoc | null> =>
|
|
606
|
+
_readMcpEndpoint(this.#client, this.#httpRequest, params.name, options),
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/** Sources: the distilled units builds cite. */
|
|
610
|
+
sources = {
|
|
611
|
+
/**
|
|
612
|
+
* List sources, optionally filtered by `status` or the `importId` they
|
|
613
|
+
* came from. `ids` is a lookup mode: it resolves those exact sources
|
|
614
|
+
* (e.g. from an entry's citations) and overrides `status` and `cursor`.
|
|
615
|
+
*/
|
|
616
|
+
list: (
|
|
617
|
+
params?: {
|
|
618
|
+
status?: Source['status']
|
|
619
|
+
importId?: string
|
|
620
|
+
ids?: string[]
|
|
621
|
+
} & ListOptions,
|
|
622
|
+
) =>
|
|
623
|
+
this.#list<SourcesResponse>('/sources', params, {
|
|
624
|
+
status: params?.status,
|
|
625
|
+
importId: params?.importId,
|
|
626
|
+
ids: params?.ids?.join(','),
|
|
627
|
+
}),
|
|
628
|
+
get: (params: {sourceId: string}, options?: RequestOptions) =>
|
|
629
|
+
this.#request<SourceDetail>(`/sources/${encodeURIComponent(params.sourceId)}`, options),
|
|
630
|
+
/**
|
|
631
|
+
* Distilled source content, optionally a line range: the evidence behind
|
|
632
|
+
* a citation or an issue.
|
|
633
|
+
*/
|
|
634
|
+
content: (
|
|
635
|
+
params: {sourceId: string; startLine?: number; endLine?: number},
|
|
636
|
+
options?: RequestOptions,
|
|
637
|
+
) =>
|
|
638
|
+
this.#request<SourceContentResponse>(
|
|
639
|
+
`/sources/${encodeURIComponent(params.sourceId)}/content`,
|
|
640
|
+
{
|
|
641
|
+
query: _query({
|
|
642
|
+
startLine: params.startLine,
|
|
643
|
+
endLine: params.endLine,
|
|
644
|
+
}),
|
|
645
|
+
...options,
|
|
646
|
+
},
|
|
647
|
+
),
|
|
648
|
+
delete: async (params: {sourceId: string}, options?: RequestOptions) => {
|
|
649
|
+
await this.#request<void>(`/sources/${encodeURIComponent(params.sourceId)}`, {
|
|
650
|
+
method: 'DELETE',
|
|
651
|
+
...options,
|
|
652
|
+
})
|
|
653
|
+
},
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Observable counterpart of {@link ContextClient}. Collection-level
|
|
659
|
+
* methods and the GROQ-backed reads; knowledge-base scoped write
|
|
660
|
+
* operations are promise-based, so use the promise client
|
|
661
|
+
* (`client.context`) for those.
|
|
662
|
+
*
|
|
663
|
+
* @beta
|
|
664
|
+
*/
|
|
665
|
+
export class ObservableContextClient {
|
|
666
|
+
#client: ObservableSanityClient
|
|
667
|
+
#httpRequest: HttpRequest
|
|
668
|
+
|
|
669
|
+
constructor(client: ObservableSanityClient, httpRequest: HttpRequest) {
|
|
670
|
+
this.#client = client
|
|
671
|
+
this.#httpRequest = httpRequest
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/** The knowledge base collection: management addressed per call. */
|
|
675
|
+
knowledgeBases = {
|
|
676
|
+
/** Create a knowledge base. Requires the org-level knowledge-base create grant. */
|
|
677
|
+
create: (
|
|
678
|
+
params: CreateKnowledgeBaseParams,
|
|
679
|
+
options?: RequestOptions,
|
|
680
|
+
): Observable<KnowledgeBase> =>
|
|
681
|
+
_observe(options?.signal, (signal) =>
|
|
682
|
+
_request<KnowledgeBase>(this.#client, this.#httpRequest, {
|
|
683
|
+
url: COLLECTION_URL,
|
|
684
|
+
method: 'POST',
|
|
685
|
+
body: params,
|
|
686
|
+
tag: options?.tag,
|
|
687
|
+
signal,
|
|
688
|
+
}),
|
|
689
|
+
),
|
|
690
|
+
/** List the organization's knowledge bases. */
|
|
691
|
+
list: (params: {organizationId: string} & ListOptions): Observable<KnowledgeBasesResponse> =>
|
|
692
|
+
_observe(params.signal, (signal) =>
|
|
693
|
+
_request<KnowledgeBasesResponse>(this.#client, this.#httpRequest, {
|
|
694
|
+
url: COLLECTION_URL,
|
|
695
|
+
query: _query({
|
|
696
|
+
organizationId: params.organizationId,
|
|
697
|
+
cursor: params.cursor,
|
|
698
|
+
limit: params.limit,
|
|
699
|
+
}),
|
|
700
|
+
tag: params.tag,
|
|
701
|
+
signal,
|
|
702
|
+
}),
|
|
703
|
+
),
|
|
704
|
+
/** Fetch a knowledge base by its id. */
|
|
705
|
+
get: (knowledgeBaseId: string, options?: RequestOptions): Observable<KnowledgeBase> =>
|
|
706
|
+
_observe(options?.signal, (signal) =>
|
|
707
|
+
_request<KnowledgeBase>(this.#client, this.#httpRequest, {
|
|
708
|
+
url: _knowledgeBaseUrl(knowledgeBaseId),
|
|
709
|
+
tag: options?.tag,
|
|
710
|
+
signal,
|
|
711
|
+
}),
|
|
712
|
+
),
|
|
713
|
+
/** Edit a knowledge base's configuration. */
|
|
714
|
+
edit: (
|
|
715
|
+
knowledgeBaseId: string,
|
|
716
|
+
params: EditKnowledgeBaseParams,
|
|
717
|
+
options?: RequestOptions,
|
|
718
|
+
): Observable<KnowledgeBase> =>
|
|
719
|
+
_observe(options?.signal, (signal) =>
|
|
720
|
+
_request<KnowledgeBase>(this.#client, this.#httpRequest, {
|
|
721
|
+
url: _knowledgeBaseUrl(knowledgeBaseId),
|
|
722
|
+
method: 'PATCH',
|
|
723
|
+
body: params,
|
|
724
|
+
tag: options?.tag,
|
|
725
|
+
signal,
|
|
726
|
+
}),
|
|
727
|
+
),
|
|
728
|
+
/** Delete a knowledge base and its generated content. */
|
|
729
|
+
delete: (knowledgeBaseId: string, options?: RequestOptions): Observable<void> =>
|
|
730
|
+
_observe(options?.signal, (signal) =>
|
|
731
|
+
_request<void>(this.#client, this.#httpRequest, {
|
|
732
|
+
url: _knowledgeBaseUrl(knowledgeBaseId),
|
|
733
|
+
method: 'DELETE',
|
|
734
|
+
tag: options?.tag,
|
|
735
|
+
signal,
|
|
736
|
+
}),
|
|
737
|
+
),
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* GROQ over the organization's Context documents (conversation telemetry
|
|
742
|
+
* today; the store holds every Context family and the caller's access
|
|
743
|
+
* decides what a query returns, so filter on `_type`).
|
|
744
|
+
*
|
|
745
|
+
* Requires `context.organizationId` in the client configuration.
|
|
746
|
+
*/
|
|
747
|
+
fetch<R = unknown>(
|
|
748
|
+
query: string,
|
|
749
|
+
params?: QueryParams,
|
|
750
|
+
options?: ContextRequestOptions,
|
|
751
|
+
): Observable<R> {
|
|
752
|
+
return _fetchStore<R>(this.#client, this.#httpRequest, query, params, options)
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Listen for changes to the organization's Context documents. Mirrors
|
|
757
|
+
* `client.listen(query, params, options)` and emits mutation events by
|
|
758
|
+
* default.
|
|
759
|
+
*/
|
|
760
|
+
listen<Opts extends ContextListenOptions | undefined = undefined>(
|
|
761
|
+
query: string,
|
|
762
|
+
params?: QueryParams,
|
|
763
|
+
options?: Opts,
|
|
764
|
+
): Observable<ListenEventFromOptions<SanityDocument, Opts>> {
|
|
765
|
+
return _listenStore(this.#client, query, params, options)
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Conversation telemetry. `threadId` identifies the conversation within
|
|
770
|
+
* the organization — reuse means the same conversation. Beyond the canned
|
|
771
|
+
* `get`, reads go through {@link fetch} and {@link listen} with GROQ
|
|
772
|
+
* (`_type == "sanity.context.conversation"`).
|
|
773
|
+
*
|
|
774
|
+
* Requires `context.organizationId` in the client configuration.
|
|
775
|
+
*/
|
|
776
|
+
conversations = {
|
|
777
|
+
/**
|
|
778
|
+
* Record a conversation. Messages replace the stored transcript
|
|
779
|
+
* wholesale; `metadata` and model fields only overwrite when present.
|
|
780
|
+
* Last write per thread wins — retries are safe.
|
|
781
|
+
*/
|
|
782
|
+
save: (
|
|
783
|
+
params: {threadId: string} & SaveConversationParams,
|
|
784
|
+
options?: RequestOptions,
|
|
785
|
+
): Observable<Conversation> => {
|
|
786
|
+
const {threadId, ...body} = params
|
|
787
|
+
return _observe(options?.signal, (signal) =>
|
|
788
|
+
_request<Conversation>(this.#client, this.#httpRequest, {
|
|
789
|
+
url: _conversationUrl(this.#client, threadId),
|
|
790
|
+
method: 'PUT',
|
|
791
|
+
body,
|
|
792
|
+
tag: options?.tag,
|
|
793
|
+
signal,
|
|
794
|
+
}),
|
|
795
|
+
)
|
|
796
|
+
},
|
|
797
|
+
/**
|
|
798
|
+
* Record the classification your own model produced for one thread:
|
|
799
|
+
* exactly one of `coreMetrics` (a verdict) or `classificationError`
|
|
800
|
+
* (why classification failed).
|
|
801
|
+
*/
|
|
802
|
+
classify: (
|
|
803
|
+
params: {threadId: string} & ClassifyConversationParams,
|
|
804
|
+
options?: RequestOptions,
|
|
805
|
+
): Observable<Conversation> => {
|
|
806
|
+
const {threadId, ...body} = params
|
|
807
|
+
return _observe(options?.signal, (signal) =>
|
|
808
|
+
_request<Conversation>(this.#client, this.#httpRequest, {
|
|
809
|
+
url: _conversationUrl(this.#client, threadId),
|
|
810
|
+
method: 'PATCH',
|
|
811
|
+
body,
|
|
812
|
+
tag: options?.tag,
|
|
813
|
+
signal,
|
|
814
|
+
}),
|
|
815
|
+
)
|
|
816
|
+
},
|
|
817
|
+
/**
|
|
818
|
+
* One recorded conversation by its thread id, or `null` when the thread
|
|
819
|
+
* was never recorded. Runs:
|
|
820
|
+
*
|
|
821
|
+
* `*[_type == "sanity.context.conversation" && organizationId == $org && threadId == $threadId][0]`
|
|
822
|
+
*
|
|
823
|
+
* For anything more, use {@link fetch}.
|
|
824
|
+
*/
|
|
825
|
+
get: (
|
|
826
|
+
params: {threadId: string},
|
|
827
|
+
options?: ContextRequestOptions,
|
|
828
|
+
): Observable<ConversationDoc | null> =>
|
|
829
|
+
_observe(options?.signal, (signal) =>
|
|
830
|
+
_readConversation(this.#client, this.#httpRequest, params.threadId, {
|
|
831
|
+
...options,
|
|
832
|
+
signal,
|
|
833
|
+
}),
|
|
834
|
+
),
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Entries: the built outline, one entry per node. Reads are canned GROQ
|
|
839
|
+
* queries against the organization's document store; for anything more,
|
|
840
|
+
* use {@link fetch}. Requires `context.organizationId` alongside the
|
|
841
|
+
* knowledge-base `resource` in the client configuration.
|
|
842
|
+
*/
|
|
843
|
+
entries = {
|
|
844
|
+
/**
|
|
845
|
+
* Every entry, path-ordered, as a metadata view (`_id`, `path`,
|
|
846
|
+
* `title`, `tldr`, `status`) with bodies excluded. Drains keyset pages
|
|
847
|
+
* internally and emits the complete set. Runs:
|
|
848
|
+
*
|
|
849
|
+
* `*[_type == "sanity.context.entry" && knowledgeBaseId == $kb && path > $after] | order(path asc) [0...200] {_id, path, title, tldr, status}`
|
|
850
|
+
*
|
|
851
|
+
* For bodies, use `entries.get` or {@link fetch}.
|
|
852
|
+
*/
|
|
853
|
+
list: (options?: ContextRequestOptions): Observable<Entry[]> =>
|
|
854
|
+
_observe(options?.signal, (signal) =>
|
|
855
|
+
_listEntries(this.#client, this.#httpRequest, _resolveKnowledgeBaseId(this.#client), {
|
|
856
|
+
...options,
|
|
857
|
+
signal,
|
|
858
|
+
}),
|
|
859
|
+
),
|
|
860
|
+
/**
|
|
861
|
+
* One entry with its full body and citations, by outline path (e.g.
|
|
862
|
+
* `billing/refunds`), or `null` when no entry sits at that path. Runs:
|
|
863
|
+
*
|
|
864
|
+
* `*[_type == "sanity.context.entry" && knowledgeBaseId == $kb && path == $path][0]`
|
|
865
|
+
*
|
|
866
|
+
* For anything more, use {@link fetch}.
|
|
867
|
+
*/
|
|
868
|
+
get: (params: {path: string}, options?: ContextRequestOptions): Observable<EntryDoc | null> =>
|
|
869
|
+
_observe(options?.signal, (signal) =>
|
|
870
|
+
_readEntry(
|
|
871
|
+
this.#client,
|
|
872
|
+
this.#httpRequest,
|
|
873
|
+
_resolveKnowledgeBaseId(this.#client),
|
|
874
|
+
params.path,
|
|
875
|
+
{...options, signal},
|
|
876
|
+
),
|
|
877
|
+
),
|
|
878
|
+
/**
|
|
879
|
+
* Rebuild one entry from its already-placed sources, by outline path.
|
|
880
|
+
* Poll the returned job with the promise client's `jobs`;
|
|
881
|
+
* `affectedEntries` lists every entry the rebuild touches.
|
|
882
|
+
*/
|
|
883
|
+
rebuild: (params: {path: string}, options?: RequestOptions): Observable<RebuildEntryResponse> =>
|
|
884
|
+
_observe(options?.signal, (signal) =>
|
|
885
|
+
_request<RebuildEntryResponse>(this.#client, this.#httpRequest, {
|
|
886
|
+
url: _knowledgeBaseUrl(
|
|
887
|
+
_resolveKnowledgeBaseId(this.#client),
|
|
888
|
+
`/entries/${encodeURIComponent(params.path)}/rebuild`,
|
|
889
|
+
),
|
|
890
|
+
method: 'POST',
|
|
891
|
+
tag: options?.tag,
|
|
892
|
+
signal,
|
|
893
|
+
}),
|
|
894
|
+
),
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* Issues: findings from builds awaiting triage. Reads are canned GROQ
|
|
899
|
+
* queries against the organization's document store; for anything more,
|
|
900
|
+
* use {@link fetch}. Requires `context.organizationId` alongside the
|
|
901
|
+
* knowledge-base `resource` in the client configuration.
|
|
902
|
+
*/
|
|
903
|
+
issues = {
|
|
904
|
+
/**
|
|
905
|
+
* Every issue on the knowledge base, oldest first, optionally narrowed
|
|
906
|
+
* to one status. Drains keyset pages internally and emits the complete
|
|
907
|
+
* set. Runs:
|
|
908
|
+
*
|
|
909
|
+
* `*[_type == "sanity.context.issue" && knowledgeBaseId == $kb && status == $status] | order(_createdAt asc, _id asc)`
|
|
910
|
+
*
|
|
911
|
+
* (the status clause only when given). For anything more, use {@link fetch}.
|
|
912
|
+
*/
|
|
913
|
+
list: (
|
|
914
|
+
params?: {status?: 'open' | 'accepted' | 'rejected'},
|
|
915
|
+
options?: ContextRequestOptions,
|
|
916
|
+
): Observable<IssueDoc[]> =>
|
|
917
|
+
_observe(options?.signal, (signal) =>
|
|
918
|
+
_listIssues(
|
|
919
|
+
this.#client,
|
|
920
|
+
this.#httpRequest,
|
|
921
|
+
_resolveKnowledgeBaseId(this.#client),
|
|
922
|
+
params?.status,
|
|
923
|
+
{...options, signal},
|
|
924
|
+
),
|
|
925
|
+
),
|
|
926
|
+
/**
|
|
927
|
+
* One issue by its document id, or `null` when it does not exist. Runs:
|
|
928
|
+
*
|
|
929
|
+
* `*[_type == "sanity.context.issue" && knowledgeBaseId == $kb && _id == $id][0]`
|
|
930
|
+
*
|
|
931
|
+
* For anything more, use {@link fetch}.
|
|
932
|
+
*/
|
|
933
|
+
get: (
|
|
934
|
+
params: {issueId: string},
|
|
935
|
+
options?: ContextRequestOptions,
|
|
936
|
+
): Observable<IssueDoc | null> =>
|
|
937
|
+
_observe(options?.signal, (signal) =>
|
|
938
|
+
_readIssue(
|
|
939
|
+
this.#client,
|
|
940
|
+
this.#httpRequest,
|
|
941
|
+
_resolveKnowledgeBaseId(this.#client),
|
|
942
|
+
params.issueId,
|
|
943
|
+
{...options, signal},
|
|
944
|
+
),
|
|
945
|
+
),
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* Instructions: standing decisions that steer every build. The canned
|
|
950
|
+
* GROQ read; writes are promise-based on `client.context`.
|
|
951
|
+
*/
|
|
952
|
+
instructions = {
|
|
953
|
+
/**
|
|
954
|
+
* Every current-schema instruction on the knowledge base, oldest first.
|
|
955
|
+
* Drains keyset pages internally and emits the complete set. Runs:
|
|
956
|
+
*
|
|
957
|
+
* `*[_type == "sanity.context.instruction" && knowledgeBaseId == $kb && schemaVersion == 1] | order(_createdAt asc, _id asc)`
|
|
958
|
+
*
|
|
959
|
+
* For anything more, use {@link fetch}. Requires `context.organizationId`
|
|
960
|
+
* alongside the knowledge-base `resource` in the client configuration.
|
|
961
|
+
*/
|
|
962
|
+
list: (options?: ContextRequestOptions): Observable<InstructionDoc[]> =>
|
|
963
|
+
_observe(options?.signal, (signal) =>
|
|
964
|
+
_listInstructions(this.#client, this.#httpRequest, _resolveKnowledgeBaseId(this.#client), {
|
|
965
|
+
...options,
|
|
966
|
+
signal,
|
|
967
|
+
}),
|
|
968
|
+
),
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* MCP endpoint configurations, org-owned documents read with canned GROQ
|
|
973
|
+
* queries. Requires `context.organizationId` in the client configuration.
|
|
974
|
+
*/
|
|
975
|
+
mcpEndpoints = {
|
|
976
|
+
/**
|
|
977
|
+
* The organization's MCP endpoint configurations, oldest first. Runs:
|
|
978
|
+
*
|
|
979
|
+
* `*[_type == "sanity.context.mcp" && organizationId == $org] | order(_createdAt asc, _id asc) [0...500]`
|
|
980
|
+
*
|
|
981
|
+
* For anything more, use {@link fetch}.
|
|
982
|
+
*/
|
|
983
|
+
list: (options?: ContextRequestOptions): Observable<McpDoc[]> =>
|
|
984
|
+
_observe(options?.signal, (signal) =>
|
|
985
|
+
_listMcpEndpoints(this.#client, this.#httpRequest, {
|
|
986
|
+
...options,
|
|
987
|
+
signal,
|
|
988
|
+
}),
|
|
989
|
+
),
|
|
990
|
+
/**
|
|
991
|
+
* One MCP endpoint configuration by its URL name, or `null` when none
|
|
992
|
+
* carries that name. Runs:
|
|
993
|
+
*
|
|
994
|
+
* `*[_type == "sanity.context.mcp" && organizationId == $org && name == $name][0]`
|
|
995
|
+
*
|
|
996
|
+
* For anything more, use {@link fetch}.
|
|
997
|
+
*/
|
|
998
|
+
get: (params: {name: string}, options?: ContextRequestOptions): Observable<McpDoc | null> =>
|
|
999
|
+
_observe(options?.signal, (signal) =>
|
|
1000
|
+
_readMcpEndpoint(this.#client, this.#httpRequest, params.name, {
|
|
1001
|
+
...options,
|
|
1002
|
+
signal,
|
|
1003
|
+
}),
|
|
1004
|
+
),
|
|
1005
|
+
}
|
|
1006
|
+
}
|