@mintlify/assistant-core
Advanced tools
| import type { AssistantCancellationSignal } from './types.js'; | ||
| export declare class CancellationController implements AssistantCancellationSignal { | ||
| private isAborted; | ||
| private readonly listeners; | ||
| get signal(): AssistantCancellationSignal; | ||
| get aborted(): boolean; | ||
| subscribe(listener: () => void): () => void; | ||
| abort(): void; | ||
| } |
| export class CancellationController { | ||
| constructor() { | ||
| this.isAborted = false; | ||
| this.listeners = new Set(); | ||
| } | ||
| get signal() { | ||
| return this; | ||
| } | ||
| get aborted() { | ||
| return this.isAborted; | ||
| } | ||
| subscribe(listener) { | ||
| if (this.isAborted) { | ||
| listener(); | ||
| return () => undefined; | ||
| } | ||
| this.listeners.add(listener); | ||
| return () => { | ||
| this.listeners.delete(listener); | ||
| }; | ||
| } | ||
| abort() { | ||
| if (this.isAborted) | ||
| return; | ||
| this.isAborted = true; | ||
| const listeners = [...this.listeners]; | ||
| this.listeners.clear(); | ||
| for (const listener of listeners) { | ||
| try { | ||
| listener(); | ||
| } | ||
| catch (_a) { | ||
| // One transport listener cannot prevent the remaining cancellation callbacks. | ||
| } | ||
| } | ||
| } | ||
| } |
| /** Supported Assistant surfaces sent with message and feedback requests. */ | ||
| export declare const ASSISTANT_SURFACES: readonly ("floating-widget" | "custom-trigger" | "headless")[]; | ||
| /** | ||
| * Compatibility major for the public Assistant core contract. | ||
| * | ||
| * This is intentionally independent from the npm package version. The core sends it as | ||
| * `coreVersion` so the service can make compatibility and deprecation decisions. | ||
| */ | ||
| export declare const ASSISTANT_CORE_API_VERSION = "1"; |
| /** Supported Assistant surfaces sent with message and feedback requests. */ | ||
| export const ASSISTANT_SURFACES = Object.freeze([ | ||
| 'floating-widget', | ||
| 'custom-trigger', | ||
| 'headless', | ||
| ]); | ||
| /** | ||
| * Compatibility major for the public Assistant core contract. | ||
| * | ||
| * This is intentionally independent from the npm package version. The core sends it as | ||
| * `coreVersion` so the service can make compatibility and deprecation decisions. | ||
| */ | ||
| export const ASSISTANT_CORE_API_VERSION = '1'; |
| import type { AssistantCore, AssistantCoreOptions } from './types.js'; | ||
| export declare function createAssistantCore(options: AssistantCoreOptions): AssistantCore; |
+476
| var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
| function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
| return new (P || (P = Promise))(function (resolve, reject) { | ||
| function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
| function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
| function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
| step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
| }); | ||
| }; | ||
| var __asyncValues = (this && this.__asyncValues) || function (o) { | ||
| if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
| var m = o[Symbol.asyncIterator], i; | ||
| return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); | ||
| function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } | ||
| function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } | ||
| }; | ||
| import { CancellationController } from './cancellation.js'; | ||
| import { ASSISTANT_CORE_API_VERSION } from './constants.js'; | ||
| import { AssistantError, getUnavailableForError, normalizeAssistantError } from './errors.js'; | ||
| let nextDefaultId = 0; | ||
| const AVAILABLE = { | ||
| unavailable: false, | ||
| type: null, | ||
| message: '', | ||
| }; | ||
| export function createAssistantCore(options) { | ||
| var _a; | ||
| const listeners = new Set(); | ||
| const metadataByMessageId = new Map(); | ||
| const createId = (_a = options.createId) !== null && _a !== void 0 ? _a : createDefaultId; | ||
| const persistedContinuation = loadContinuation(options); | ||
| let nextOperationId = 0; | ||
| let activeOperation; | ||
| let destroyed = false; | ||
| let snapshot = { | ||
| status: 'ready', | ||
| messages: [], | ||
| data: [], | ||
| context: copyContext(options.context), | ||
| threadId: persistedContinuation === null || persistedContinuation === void 0 ? void 0 : persistedContinuation.threadId, | ||
| threadKey: persistedContinuation === null || persistedContinuation === void 0 ? void 0 : persistedContinuation.threadKey, | ||
| unavailable: AVAILABLE, | ||
| }; | ||
| const publish = (nextSnapshot) => { | ||
| snapshot = nextSnapshot; | ||
| for (const listener of [...listeners]) { | ||
| if (!listeners.has(listener)) | ||
| continue; | ||
| try { | ||
| listener(snapshot); | ||
| } | ||
| catch (_a) { | ||
| // A consumer callback cannot prevent other subscribers from receiving state. | ||
| } | ||
| } | ||
| }; | ||
| const emitLifecycleEvent = (event) => { | ||
| var _a; | ||
| try { | ||
| (_a = options.onEvent) === null || _a === void 0 ? void 0 : _a.call(options, event); | ||
| } | ||
| catch (_b) { | ||
| // Analytics and other observers must not affect core state transitions. | ||
| } | ||
| }; | ||
| const detachActiveOperation = () => { | ||
| const operation = activeOperation; | ||
| activeOperation = undefined; | ||
| return operation; | ||
| }; | ||
| const abort = () => { | ||
| const operation = detachActiveOperation(); | ||
| if (operation === undefined) | ||
| return; | ||
| const messages = markAssistantMessageAborted(snapshot.messages, operation.assistantMessageId); | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'ready', messages, error: undefined })); | ||
| operation.controller.abort(); | ||
| }; | ||
| const beginOperation = (surface, entryPoint) => { | ||
| const operation = { | ||
| id: ++nextOperationId, | ||
| controller: new CancellationController(), | ||
| surface, | ||
| entryPoint, | ||
| }; | ||
| activeOperation = operation; | ||
| return operation; | ||
| }; | ||
| const runOperation = (operation, userMessage, regenerate) => __awaiter(this, void 0, void 0, function* () { | ||
| var _a, e_1, _b, _c; | ||
| var _d, _e, _f, _g, _h; | ||
| const request = { | ||
| messages: snapshot.messages, | ||
| surface: operation.surface, | ||
| entryPoint: operation.entryPoint, | ||
| loaderVersion: options.metadata.loaderVersion, | ||
| coreVersion: ASSISTANT_CORE_API_VERSION, | ||
| context: (_d = userMessage.context) === null || _d === void 0 ? void 0 : _d.items, | ||
| currentPath: (_e = userMessage.context) === null || _e === void 0 ? void 0 : _e.currentPath, | ||
| version: (_f = userMessage.context) === null || _f === void 0 ? void 0 : _f.version, | ||
| language: (_g = userMessage.context) === null || _g === void 0 ? void 0 : _g.language, | ||
| product: (_h = userMessage.context) === null || _h === void 0 ? void 0 : _h.product, | ||
| threadId: snapshot.threadId, | ||
| threadKey: snapshot.threadKey, | ||
| regenerate: regenerate || undefined, | ||
| }; | ||
| try { | ||
| try { | ||
| for (var _j = true, _k = __asyncValues(options.transport.send(request, operation.controller.signal)), _l; _l = yield _k.next(), _a = _l.done, !_a; _j = true) { | ||
| _c = _l.value; | ||
| _j = false; | ||
| const event = _c; | ||
| if (!isCurrentOperation(operation)) | ||
| return snapshot; | ||
| applyTransportEvent(operation, event); | ||
| } | ||
| } | ||
| catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
| finally { | ||
| try { | ||
| if (!_j && !_a && (_b = _k.return)) yield _b.call(_k); | ||
| } | ||
| finally { if (e_1) throw e_1.error; } | ||
| } | ||
| if (!isCurrentOperation(operation)) | ||
| return snapshot; | ||
| finishOperation(operation); | ||
| return snapshot; | ||
| } | ||
| catch (error) { | ||
| if (operation.controller.signal.aborted || !isCurrentOperation(operation)) | ||
| return snapshot; | ||
| activeOperation = undefined; | ||
| const normalizedError = normalizeAssistantError(error); | ||
| const errorSnapshot = normalizedError.toSnapshot(); | ||
| const messages = markAssistantMessageErrored(snapshot.messages, operation.assistantMessageId); | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'error', messages, error: errorSnapshot, unavailable: getUnavailableForError(normalizedError) })); | ||
| emitLifecycleEvent({ | ||
| type: 'errored', | ||
| error: errorSnapshot, | ||
| metadata: getOperationMetadata(options.metadata, operation), | ||
| }); | ||
| throw normalizedError; | ||
| } | ||
| }); | ||
| const applyTransportEvent = (operation, event) => { | ||
| var _a, _b; | ||
| if (event.type === 'start') { | ||
| const serverMessageId = (_a = event.messageId) !== null && _a !== void 0 ? _a : operation.serverMessageId; | ||
| operation.serverMessageId = serverMessageId; | ||
| const { threadId, threadKey } = resolveContinuation(event.threadId, event.threadKey); | ||
| const { assistantMessage, messages } = ensureAssistantMessage(operation, snapshot.messages); | ||
| const nextMessages = serverMessageId === undefined || assistantMessage.messageId === serverMessageId | ||
| ? messages | ||
| : replaceMessage(messages, Object.assign(Object.assign({}, assistantMessage), { messageId: serverMessageId })); | ||
| if (event.threadId !== undefined || event.threadKey !== undefined) { | ||
| saveContinuation(options, threadId, threadKey); | ||
| } | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'streaming', messages: nextMessages, threadId, threadKey })); | ||
| return; | ||
| } | ||
| if (event.type === 'text-delta') { | ||
| const { assistantMessage, messages } = ensureAssistantMessage(operation, snapshot.messages); | ||
| const content = `${assistantMessage.content}${event.delta}`; | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'streaming', messages: replaceMessage(messages, Object.assign(Object.assign({}, assistantMessage), { content, parts: appendTextDelta(assistantMessage.parts, event.delta), status: 'streaming' })) })); | ||
| return; | ||
| } | ||
| if (event.type === 'message') { | ||
| operation.serverMessageId = (_b = event.messageId) !== null && _b !== void 0 ? _b : operation.serverMessageId; | ||
| const { assistantMessage, messages } = ensureAssistantMessage(operation, snapshot.messages); | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'streaming', messages: replaceMessage(messages, Object.assign(Object.assign({}, assistantMessage), { content: event.content, parts: event.parts === undefined ? partsForContent(event.content) : [...event.parts], status: 'streaming', messageId: operation.serverMessageId })) })); | ||
| return; | ||
| } | ||
| if (event.type === 'data') { | ||
| publish(Object.assign(Object.assign({}, snapshot), { data: [...snapshot.data, event.data] })); | ||
| return; | ||
| } | ||
| finishOperation(operation, event); | ||
| }; | ||
| const ensureAssistantMessage = (operation, messages) => { | ||
| const existing = getMessage(messages, operation.assistantMessageId); | ||
| if (existing !== undefined) | ||
| return { assistantMessage: existing, messages }; | ||
| const assistantMessage = { | ||
| id: createId(), | ||
| role: 'assistant', | ||
| content: '', | ||
| parts: [], | ||
| status: 'streaming', | ||
| messageId: operation.serverMessageId, | ||
| }; | ||
| operation.assistantMessageId = assistantMessage.id; | ||
| metadataByMessageId.set(assistantMessage.id, getOperationMetadata(options.metadata, operation)); | ||
| return { | ||
| assistantMessage, | ||
| messages: [...messages, assistantMessage], | ||
| }; | ||
| }; | ||
| const finishOperation = (operation, event) => { | ||
| var _a, _b, _c; | ||
| if (!isCurrentOperation(operation)) | ||
| return; | ||
| operation.serverMessageId = (_a = event === null || event === void 0 ? void 0 : event.messageId) !== null && _a !== void 0 ? _a : operation.serverMessageId; | ||
| const { threadId, threadKey } = resolveContinuation(event === null || event === void 0 ? void 0 : event.threadId, event === null || event === void 0 ? void 0 : event.threadKey); | ||
| const { assistantMessage, messages } = ensureAssistantMessage(operation, snapshot.messages); | ||
| const content = (_b = event === null || event === void 0 ? void 0 : event.content) !== null && _b !== void 0 ? _b : assistantMessage.content; | ||
| const completeMessage = Object.assign(Object.assign({}, assistantMessage), { content, parts: (event === null || event === void 0 ? void 0 : event.parts) !== undefined | ||
| ? [...event.parts] | ||
| : (event === null || event === void 0 ? void 0 : event.content) === undefined | ||
| ? assistantMessage.parts | ||
| : partsForContent(content), status: 'complete', messageId: (_c = operation.serverMessageId) !== null && _c !== void 0 ? _c : assistantMessage.messageId }); | ||
| activeOperation = undefined; | ||
| if ((event === null || event === void 0 ? void 0 : event.threadId) !== undefined || (event === null || event === void 0 ? void 0 : event.threadKey) !== undefined) { | ||
| saveContinuation(options, threadId, threadKey); | ||
| } | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'ready', messages: replaceMessage(messages, completeMessage), threadId, | ||
| threadKey, error: undefined, unavailable: AVAILABLE })); | ||
| emitLifecycleEvent({ | ||
| type: 'completed', | ||
| threadId: snapshot.threadId, | ||
| messageId: completeMessage.messageId, | ||
| metadata: getOperationMetadata(options.metadata, operation), | ||
| }); | ||
| }; | ||
| const resolveContinuation = (threadId, threadKey) => { | ||
| return { | ||
| threadId: threadId !== null && threadId !== void 0 ? threadId : snapshot.threadId, | ||
| threadKey: threadKey !== null && threadKey !== void 0 ? threadKey : snapshot.threadKey, | ||
| }; | ||
| }; | ||
| const isCurrentOperation = (operation) => { | ||
| return (activeOperation === null || activeOperation === void 0 ? void 0 : activeOperation.id) === operation.id && !destroyed; | ||
| }; | ||
| const send = (input) => __awaiter(this, void 0, void 0, function* () { | ||
| var _a, _b, _c; | ||
| assertUsable(destroyed); | ||
| if (activeOperation !== undefined) { | ||
| throw new AssistantError({ | ||
| code: 'invalid_state', | ||
| message: 'A message is already in progress.', | ||
| retryable: true, | ||
| }); | ||
| } | ||
| if (input.content.trim().length === 0) { | ||
| throw new AssistantError({ | ||
| code: 'invalid_input', | ||
| message: 'A message must contain text.', | ||
| retryable: true, | ||
| }); | ||
| } | ||
| const context = copyContext((_a = input.context) !== null && _a !== void 0 ? _a : snapshot.context); | ||
| const surface = (_b = input.surface) !== null && _b !== void 0 ? _b : options.metadata.surface; | ||
| const entryPoint = (_c = input.entryPoint) !== null && _c !== void 0 ? _c : options.metadata.entryPoint; | ||
| const userMessage = { | ||
| id: createId(), | ||
| role: 'user', | ||
| content: input.content, | ||
| parts: partsForContent(input.content), | ||
| status: 'complete', | ||
| context, | ||
| }; | ||
| metadataByMessageId.set(userMessage.id, resolveMetadata(options.metadata, surface, entryPoint)); | ||
| const operation = beginOperation(surface, entryPoint); | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'submitted', messages: [...snapshot.messages, userMessage], data: [], error: undefined, unavailable: AVAILABLE })); | ||
| if (!isCurrentOperation(operation)) | ||
| return snapshot; | ||
| return runOperation(operation, userMessage, false); | ||
| }); | ||
| const retry = () => __awaiter(this, void 0, void 0, function* () { | ||
| var _a; | ||
| assertUsable(destroyed); | ||
| if (activeOperation !== undefined) { | ||
| throw new AssistantError({ | ||
| code: 'invalid_state', | ||
| message: 'A message is already in progress.', | ||
| retryable: true, | ||
| }); | ||
| } | ||
| const userMessageIndex = findLastUserMessageIndex(snapshot.messages); | ||
| const userMessage = snapshot.messages[userMessageIndex]; | ||
| if (userMessageIndex < 0 || userMessage === undefined) { | ||
| throw new AssistantError({ | ||
| code: 'invalid_state', | ||
| message: 'There is no message to retry.', | ||
| retryable: false, | ||
| }); | ||
| } | ||
| const metadata = (_a = metadataByMessageId.get(userMessage.id)) !== null && _a !== void 0 ? _a : resolveMetadata(options.metadata); | ||
| const operation = beginOperation(metadata.surface, metadata.entryPoint); | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'submitted', messages: snapshot.messages.slice(0, userMessageIndex + 1), data: [], error: undefined, unavailable: AVAILABLE })); | ||
| if (!isCurrentOperation(operation)) | ||
| return snapshot; | ||
| return runOperation(operation, userMessage, true); | ||
| }); | ||
| const newThread = () => { | ||
| var _a; | ||
| assertUsable(destroyed); | ||
| const operation = detachActiveOperation(); | ||
| metadataByMessageId.clear(); | ||
| try { | ||
| (_a = options.storage) === null || _a === void 0 ? void 0 : _a.clearContinuation(); | ||
| } | ||
| catch (_b) { | ||
| // Storage failures do not make the in-memory Assistant unusable. | ||
| } | ||
| publish({ | ||
| status: 'ready', | ||
| messages: [], | ||
| data: [], | ||
| context: snapshot.context, | ||
| unavailable: AVAILABLE, | ||
| }); | ||
| operation === null || operation === void 0 ? void 0 : operation.controller.abort(); | ||
| emitLifecycleEvent({ type: 'new-thread', metadata: resolveMetadata(options.metadata) }); | ||
| return snapshot; | ||
| }; | ||
| const setContext = (context) => { | ||
| assertUsable(destroyed); | ||
| publish(Object.assign(Object.assign({}, snapshot), { context: copyContext(context) })); | ||
| }; | ||
| const submitFeedback = (input) => __awaiter(this, void 0, void 0, function* () { | ||
| var _a; | ||
| assertUsable(destroyed); | ||
| const message = snapshot.messages.find((candidate) => candidate.role === 'assistant' && | ||
| (candidate.id === input.messageId || candidate.messageId === input.messageId)); | ||
| if ((message === null || message === void 0 ? void 0 : message.messageId) === undefined || message.status !== 'complete') { | ||
| throw new AssistantError({ | ||
| code: 'invalid_input', | ||
| message: 'Feedback requires a completed Assistant message.', | ||
| retryable: false, | ||
| }); | ||
| } | ||
| const metadata = (_a = metadataByMessageId.get(message.id)) !== null && _a !== void 0 ? _a : resolveMetadata(options.metadata); | ||
| yield options.transport.submitFeedback({ | ||
| messageId: message.messageId, | ||
| feedback: input.feedback, | ||
| surface: metadata.surface, | ||
| entryPoint: metadata.entryPoint, | ||
| loaderVersion: metadata.loaderVersion, | ||
| coreVersion: metadata.coreVersion, | ||
| threadId: snapshot.threadId, | ||
| threadKey: snapshot.threadKey, | ||
| }); | ||
| publish(Object.assign(Object.assign({}, snapshot), { messages: replaceMessage(snapshot.messages, Object.assign(Object.assign({}, message), { feedback: input.feedback })) })); | ||
| emitLifecycleEvent({ | ||
| type: 'feedback-submitted', | ||
| messageId: message.messageId, | ||
| feedback: input.feedback, | ||
| metadata, | ||
| }); | ||
| }); | ||
| const subscribe = (listener) => { | ||
| assertUsable(destroyed); | ||
| listeners.add(listener); | ||
| return () => { | ||
| listeners.delete(listener); | ||
| }; | ||
| }; | ||
| const destroy = () => { | ||
| var _a, _b; | ||
| if (destroyed) | ||
| return; | ||
| const operation = detachActiveOperation(); | ||
| destroyed = true; | ||
| metadataByMessageId.clear(); | ||
| publish(Object.assign(Object.assign({}, snapshot), { status: 'destroyed', messages: markAssistantMessageAborted(snapshot.messages, operation === null || operation === void 0 ? void 0 : operation.assistantMessageId) })); | ||
| listeners.clear(); | ||
| operation === null || operation === void 0 ? void 0 : operation.controller.abort(); | ||
| (_b = (_a = options.transport).destroy) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
| }; | ||
| return { | ||
| send, | ||
| abort, | ||
| retry, | ||
| newThread, | ||
| setContext, | ||
| submitFeedback, | ||
| getSnapshot: () => snapshot, | ||
| subscribe, | ||
| destroy, | ||
| }; | ||
| } | ||
| function copyContext(context) { | ||
| var _a; | ||
| if (context === undefined) | ||
| return undefined; | ||
| return { | ||
| items: (_a = context.items) === null || _a === void 0 ? void 0 : _a.map((item) => (Object.assign({}, item))), | ||
| currentPath: context.currentPath, | ||
| version: context.version, | ||
| language: context.language, | ||
| product: context.product, | ||
| }; | ||
| } | ||
| function getOperationMetadata(metadata, operation) { | ||
| return resolveMetadata(metadata, operation.surface, operation.entryPoint); | ||
| } | ||
| function resolveMetadata(metadata, surface = metadata.surface, entryPoint = metadata.entryPoint) { | ||
| return Object.assign(Object.assign({}, metadata), { surface, | ||
| entryPoint, coreVersion: ASSISTANT_CORE_API_VERSION }); | ||
| } | ||
| function createDefaultId() { | ||
| nextDefaultId += 1; | ||
| return `assistant-message-${nextDefaultId}`; | ||
| } | ||
| function partsForContent(content) { | ||
| return content.length === 0 ? [] : [{ type: 'text', text: content }]; | ||
| } | ||
| function appendTextDelta(parts, delta) { | ||
| const lastPart = parts[parts.length - 1]; | ||
| if ((lastPart === null || lastPart === void 0 ? void 0 : lastPart.type) === 'text') { | ||
| return [...parts.slice(0, -1), { type: 'text', text: `${lastPart.text}${delta}` }]; | ||
| } | ||
| return [...parts, { type: 'text', text: delta }]; | ||
| } | ||
| function getMessage(messages, id) { | ||
| if (id === undefined) | ||
| return undefined; | ||
| return messages.find((message) => message.id === id); | ||
| } | ||
| function replaceMessage(messages, message) { | ||
| return messages.map((candidate) => (candidate.id === message.id ? message : candidate)); | ||
| } | ||
| function findLastUserMessageIndex(messages) { | ||
| var _a; | ||
| for (let index = messages.length - 1; index >= 0; index -= 1) { | ||
| if (((_a = messages[index]) === null || _a === void 0 ? void 0 : _a.role) === 'user') | ||
| return index; | ||
| } | ||
| return -1; | ||
| } | ||
| function markAssistantMessageAborted(messages, id) { | ||
| if (id === undefined) | ||
| return messages; | ||
| return messages.map((message) => message.id === id ? Object.assign(Object.assign({}, message), { status: 'aborted' }) : message); | ||
| } | ||
| function markAssistantMessageErrored(messages, id) { | ||
| if (id === undefined) | ||
| return messages; | ||
| return messages.map((message) => (message.id === id ? Object.assign(Object.assign({}, message), { status: 'error' }) : message)); | ||
| } | ||
| function assertUsable(destroyed) { | ||
| if (!destroyed) | ||
| return; | ||
| throw new AssistantError({ | ||
| code: 'destroyed', | ||
| message: 'This Assistant client has been destroyed.', | ||
| retryable: false, | ||
| }); | ||
| } | ||
| function loadContinuation(options) { | ||
| var _a; | ||
| try { | ||
| const continuation = (_a = options.storage) === null || _a === void 0 ? void 0 : _a.loadContinuation(); | ||
| if (continuation === undefined) | ||
| return undefined; | ||
| return { | ||
| threadId: continuation.threadId, | ||
| threadKey: continuation.threadKey, | ||
| }; | ||
| } | ||
| catch (_b) { | ||
| return undefined; | ||
| } | ||
| } | ||
| function saveContinuation(options, threadId, threadKey) { | ||
| var _a; | ||
| if (threadId === undefined && threadKey === undefined) | ||
| return; | ||
| try { | ||
| (_a = options.storage) === null || _a === void 0 ? void 0 : _a.saveContinuation({ threadId, threadKey }); | ||
| } | ||
| catch (_b) { | ||
| // Storage failures do not make the in-memory Assistant unusable. | ||
| } | ||
| } |
| import type { AssistantErrorCode, AssistantErrorSnapshot, AssistantUnavailable, AssistantUnavailableType } from './types.js'; | ||
| export declare class AssistantError extends Error { | ||
| readonly code: AssistantErrorCode; | ||
| readonly retryable: boolean; | ||
| readonly status?: number; | ||
| readonly unavailableType?: AssistantUnavailableType; | ||
| readonly rayId?: string; | ||
| constructor(options: { | ||
| code: AssistantErrorCode; | ||
| message: string; | ||
| retryable: boolean; | ||
| status?: number; | ||
| unavailableType?: AssistantUnavailableType; | ||
| rayId?: string; | ||
| }); | ||
| toSnapshot(): AssistantErrorSnapshot; | ||
| } | ||
| export declare class AssistantTransportError extends AssistantError { | ||
| constructor(options?: { | ||
| message?: string; | ||
| status?: number; | ||
| unavailableType?: AssistantUnavailableType; | ||
| rayId?: string; | ||
| retryable?: boolean; | ||
| }); | ||
| } | ||
| export declare function getUnavailableForStatus(status?: number, rayId?: string): AssistantUnavailable; | ||
| export declare function normalizeAssistantError(error: unknown): AssistantError; | ||
| export declare function getUnavailableForError(error: AssistantError): AssistantUnavailable; |
+173
| const UNAVAILABLE_CONFIG = { | ||
| 402: { | ||
| type: 'payment', | ||
| message: 'Usage of this feature is temporarily limited. Please try again later or contact the site owner to restore access.', | ||
| }, | ||
| 403: { | ||
| type: 'rate_limited', | ||
| message: "You're sending too many messages. Please wait a moment and try again.", | ||
| }, | ||
| 404: { | ||
| type: 'not_found', | ||
| message: 'There was an error sending your message. Please refresh and try again.', | ||
| }, | ||
| 413: { | ||
| type: 'thread_limit', | ||
| message: 'You have reached the maximum number of messages in a thread. Please start a new thread to continue.', | ||
| }, | ||
| 418: { | ||
| type: 'blocked', | ||
| message: 'The assistant is unavailable from your network. If you are using a VPN, please turn it off and try again.', | ||
| }, | ||
| 420: { | ||
| type: 'heuristic_blocked', | ||
| message: 'Your request could not be verified. Please refresh and try again.', | ||
| }, | ||
| 429: { | ||
| type: 'rate_limited', | ||
| message: "You're sending too many messages. Please wait a moment and try again.", | ||
| }, | ||
| }; | ||
| const DEFAULT_UNAVAILABLE = { | ||
| type: 'unknown', | ||
| message: 'This feature is temporarily unavailable. Please try again later or contact the site owner to restore access.', | ||
| }; | ||
| const CAPTCHA_MESSAGE = 'Unable to verify your browser. Please try again. If this issue persists, refresh your browser.'; | ||
| const STREAM_ERROR_MESSAGE = 'There was an error generating a response. Please check your connection and try again.'; | ||
| export class AssistantError extends Error { | ||
| constructor(options) { | ||
| super(options.message); | ||
| this.name = 'AssistantError'; | ||
| this.code = options.code; | ||
| this.retryable = options.retryable; | ||
| this.status = options.status; | ||
| this.unavailableType = options.unavailableType; | ||
| this.rayId = options.rayId; | ||
| } | ||
| toSnapshot() { | ||
| return { | ||
| name: 'AssistantError', | ||
| code: this.code, | ||
| message: this.message, | ||
| retryable: this.retryable, | ||
| status: this.status, | ||
| unavailableType: this.unavailableType, | ||
| rayId: this.rayId, | ||
| }; | ||
| } | ||
| } | ||
| export class AssistantTransportError extends AssistantError { | ||
| constructor(options) { | ||
| const normalized = getTransportErrorOptions(options); | ||
| super(normalized); | ||
| this.name = 'AssistantError'; | ||
| } | ||
| } | ||
| export function getUnavailableForStatus(status, rayId) { | ||
| if (status === 400 || status === 419 || status === 450) { | ||
| return { | ||
| unavailable: true, | ||
| type: 'captcha_required', | ||
| message: CAPTCHA_MESSAGE, | ||
| rayId, | ||
| }; | ||
| } | ||
| const config = status === undefined ? DEFAULT_UNAVAILABLE : UNAVAILABLE_CONFIG[status]; | ||
| if (config === undefined) { | ||
| return { | ||
| unavailable: true, | ||
| type: 'stream_error', | ||
| message: STREAM_ERROR_MESSAGE, | ||
| rayId, | ||
| }; | ||
| } | ||
| return { | ||
| unavailable: true, | ||
| type: config.type, | ||
| message: config.message, | ||
| rayId, | ||
| }; | ||
| } | ||
| export function normalizeAssistantError(error) { | ||
| if (error instanceof AssistantError) | ||
| return error; | ||
| return new AssistantError({ | ||
| code: 'stream_error', | ||
| message: STREAM_ERROR_MESSAGE, | ||
| retryable: true, | ||
| }); | ||
| } | ||
| function getTransportErrorOptions(options) { | ||
| var _a, _b, _c, _d, _e, _f, _g, _h; | ||
| const status = options === null || options === void 0 ? void 0 : options.status; | ||
| if ((options === null || options === void 0 ? void 0 : options.unavailableType) !== undefined) { | ||
| const unavailable = getUnavailableForType(options.unavailableType, options.rayId); | ||
| return { | ||
| code: options.unavailableType === 'captcha_required' ? 'captcha_required' : 'unavailable', | ||
| message: (_a = options.message) !== null && _a !== void 0 ? _a : unavailable.message, | ||
| retryable: (_b = options.retryable) !== null && _b !== void 0 ? _b : isRetryableType(options.unavailableType), | ||
| status, | ||
| unavailableType: options.unavailableType, | ||
| rayId: options.rayId, | ||
| }; | ||
| } | ||
| if (status !== undefined && | ||
| (UNAVAILABLE_CONFIG[status] !== undefined || isCaptchaStatus(status))) { | ||
| const unavailable = getUnavailableForStatus(status, options === null || options === void 0 ? void 0 : options.rayId); | ||
| return { | ||
| code: unavailable.type === 'captcha_required' ? 'captcha_required' : 'unavailable', | ||
| message: (_c = options === null || options === void 0 ? void 0 : options.message) !== null && _c !== void 0 ? _c : unavailable.message, | ||
| retryable: (_d = options === null || options === void 0 ? void 0 : options.retryable) !== null && _d !== void 0 ? _d : isRetryableType((_e = unavailable.type) !== null && _e !== void 0 ? _e : 'unknown'), | ||
| status, | ||
| unavailableType: (_f = unavailable.type) !== null && _f !== void 0 ? _f : 'unknown', | ||
| rayId: options === null || options === void 0 ? void 0 : options.rayId, | ||
| }; | ||
| } | ||
| return { | ||
| code: 'transport_error', | ||
| message: (_g = options === null || options === void 0 ? void 0 : options.message) !== null && _g !== void 0 ? _g : STREAM_ERROR_MESSAGE, | ||
| retryable: (_h = options === null || options === void 0 ? void 0 : options.retryable) !== null && _h !== void 0 ? _h : true, | ||
| status, | ||
| rayId: options === null || options === void 0 ? void 0 : options.rayId, | ||
| }; | ||
| } | ||
| function getUnavailableForType(type, rayId) { | ||
| var _a; | ||
| if (type === 'captcha_required') { | ||
| return { unavailable: true, type, message: CAPTCHA_MESSAGE, rayId }; | ||
| } | ||
| if (type === 'stream_error') { | ||
| return { unavailable: true, type, message: STREAM_ERROR_MESSAGE, rayId }; | ||
| } | ||
| const config = Object.values(UNAVAILABLE_CONFIG).find((value) => value.type === type); | ||
| return { | ||
| unavailable: true, | ||
| type, | ||
| message: (_a = config === null || config === void 0 ? void 0 : config.message) !== null && _a !== void 0 ? _a : DEFAULT_UNAVAILABLE.message, | ||
| rayId, | ||
| }; | ||
| } | ||
| function isCaptchaStatus(status) { | ||
| return status === 400 || status === 419 || status === 450; | ||
| } | ||
| function isRetryableType(type) { | ||
| return type !== 'payment' && type !== 'blocked' && type !== 'thread_limit'; | ||
| } | ||
| export function getUnavailableForError(error) { | ||
| if (error.unavailableType !== undefined) { | ||
| return getUnavailableForType(error.unavailableType, error.rayId); | ||
| } | ||
| if (error.code === 'stream_error' || error.code === 'transport_error') { | ||
| return { | ||
| unavailable: true, | ||
| type: 'stream_error', | ||
| message: STREAM_ERROR_MESSAGE, | ||
| rayId: error.rayId, | ||
| }; | ||
| } | ||
| return { | ||
| unavailable: false, | ||
| type: null, | ||
| message: '', | ||
| }; | ||
| } |
| export { ASSISTANT_CORE_API_VERSION, ASSISTANT_SURFACES } from './constants.js'; | ||
| export { createAssistantCore } from './core.js'; | ||
| export { AssistantError, AssistantTransportError, getUnavailableForStatus } from './errors.js'; | ||
| export type { AssistantCancellationSignal, AssistantContext, AssistantContextItem, AssistantContinuation, AssistantCore, AssistantCoreOptions, AssistantDataPart, AssistantErrorCode, AssistantErrorSnapshot, AssistantFeedback, AssistantFeedbackInput, AssistantLifecycleEvent, AssistantLifecycleMetadata, AssistantMessage, AssistantMessagePart, AssistantMessageStatus, AssistantMetadata, AssistantSendInput, AssistantSnapshot, AssistantSourcePart, AssistantStatus, AssistantStorageAdapter, AssistantSurface, AssistantTextPart, AssistantToolPart, AssistantTransport, AssistantTransportEvent, AssistantTransportFeedbackRequest, AssistantTransportSendRequest, AssistantUnavailable, AssistantUnavailableType, } from './types.js'; |
| export { ASSISTANT_CORE_API_VERSION, ASSISTANT_SURFACES } from './constants.js'; | ||
| export { createAssistantCore } from './core.js'; | ||
| export { AssistantError, AssistantTransportError, getUnavailableForStatus } from './errors.js'; |
+200
| export type AssistantSurface = 'floating-widget' | 'custom-trigger' | 'headless'; | ||
| export type AssistantContextItem = { | ||
| readonly type: 'code' | 'textSelection'; | ||
| readonly value: string; | ||
| readonly path?: string; | ||
| readonly elementId?: string; | ||
| }; | ||
| export type AssistantContext = { | ||
| readonly items?: ReadonlyArray<AssistantContextItem>; | ||
| readonly currentPath?: string; | ||
| readonly version?: string; | ||
| readonly language?: string; | ||
| readonly product?: string; | ||
| }; | ||
| export type AssistantFeedback = 'positive' | 'negative'; | ||
| export type AssistantUnavailableType = 'rate_limited' | 'blocked' | 'heuristic_blocked' | 'thread_limit' | 'payment' | 'unknown' | 'not_found' | 'captcha_required' | 'stream_error'; | ||
| export type AssistantUnavailable = { | ||
| readonly unavailable: boolean; | ||
| readonly type: AssistantUnavailableType | null; | ||
| readonly message: string; | ||
| readonly rayId?: string; | ||
| }; | ||
| export type AssistantTextPart = { | ||
| readonly type: 'text'; | ||
| readonly text: string; | ||
| }; | ||
| export type AssistantToolPart = { | ||
| readonly type: 'tool'; | ||
| readonly toolCallId: string; | ||
| readonly toolName: string; | ||
| readonly state: 'input-streaming' | 'input-available' | 'output-available' | 'output-error'; | ||
| readonly input?: unknown; | ||
| readonly output?: unknown; | ||
| readonly errorText?: string; | ||
| }; | ||
| export type AssistantSourcePart = { | ||
| readonly type: 'source'; | ||
| readonly title?: string; | ||
| readonly url: string; | ||
| }; | ||
| export type AssistantDataPart = { | ||
| readonly type: 'data'; | ||
| readonly data: unknown; | ||
| }; | ||
| export type AssistantMessagePart = AssistantTextPart | AssistantToolPart | AssistantSourcePart | AssistantDataPart; | ||
| export type AssistantMessageStatus = 'streaming' | 'complete' | 'error' | 'aborted'; | ||
| export type AssistantMessage = { | ||
| readonly id: string; | ||
| readonly role: 'user' | 'assistant'; | ||
| readonly content: string; | ||
| readonly parts: ReadonlyArray<AssistantMessagePart>; | ||
| readonly status: AssistantMessageStatus; | ||
| readonly context?: AssistantContext; | ||
| /** The server message ID returned through X-Message-Id. */ | ||
| readonly messageId?: string; | ||
| readonly feedback?: AssistantFeedback; | ||
| }; | ||
| export type AssistantStatus = 'ready' | 'submitted' | 'streaming' | 'error' | 'destroyed'; | ||
| export type AssistantErrorCode = 'aborted' | 'captcha_required' | 'destroyed' | 'invalid_input' | 'invalid_state' | 'stream_error' | 'transport_error' | 'unavailable'; | ||
| export type AssistantErrorSnapshot = { | ||
| readonly name: 'AssistantError'; | ||
| readonly code: AssistantErrorCode; | ||
| readonly message: string; | ||
| readonly retryable: boolean; | ||
| readonly status?: number; | ||
| readonly unavailableType?: AssistantUnavailableType; | ||
| readonly rayId?: string; | ||
| }; | ||
| export type AssistantSnapshot = { | ||
| readonly status: AssistantStatus; | ||
| readonly messages: ReadonlyArray<AssistantMessage>; | ||
| readonly data: ReadonlyArray<unknown>; | ||
| readonly context?: AssistantContext; | ||
| readonly threadId?: string; | ||
| readonly threadKey?: string; | ||
| readonly error?: AssistantErrorSnapshot; | ||
| readonly unavailable: AssistantUnavailable; | ||
| }; | ||
| export type AssistantContinuation = { | ||
| readonly threadId?: string; | ||
| readonly threadKey?: string; | ||
| }; | ||
| export interface AssistantStorageAdapter { | ||
| loadContinuation(): AssistantContinuation | undefined; | ||
| saveContinuation(continuation: AssistantContinuation): void; | ||
| clearContinuation(): void; | ||
| } | ||
| export interface AssistantCancellationSignal { | ||
| readonly aborted: boolean; | ||
| subscribe(listener: () => void): () => void; | ||
| } | ||
| export type AssistantTransportSendRequest = { | ||
| readonly messages: ReadonlyArray<AssistantMessage>; | ||
| readonly surface: AssistantSurface; | ||
| readonly entryPoint: string; | ||
| readonly loaderVersion?: string; | ||
| readonly coreVersion: string; | ||
| readonly context?: ReadonlyArray<AssistantContextItem>; | ||
| readonly currentPath?: string; | ||
| readonly version?: string; | ||
| readonly language?: string; | ||
| readonly product?: string; | ||
| readonly threadId?: string; | ||
| readonly threadKey?: string; | ||
| readonly regenerate?: boolean; | ||
| }; | ||
| export type AssistantTransportFeedbackRequest = { | ||
| readonly messageId: string; | ||
| readonly feedback: AssistantFeedback; | ||
| readonly surface: AssistantSurface; | ||
| readonly entryPoint: string; | ||
| readonly loaderVersion?: string; | ||
| readonly coreVersion: string; | ||
| readonly threadId?: string; | ||
| readonly threadKey?: string; | ||
| }; | ||
| export type AssistantTransportEvent = { | ||
| type: 'start'; | ||
| threadId?: string; | ||
| threadKey?: string; | ||
| messageId?: string; | ||
| } | { | ||
| type: 'text-delta'; | ||
| delta: string; | ||
| } | { | ||
| type: 'message'; | ||
| content: string; | ||
| parts?: ReadonlyArray<AssistantMessagePart>; | ||
| messageId?: string; | ||
| } | { | ||
| type: 'data'; | ||
| data: unknown; | ||
| } | { | ||
| type: 'finish'; | ||
| content?: string; | ||
| parts?: ReadonlyArray<AssistantMessagePart>; | ||
| threadId?: string; | ||
| threadKey?: string; | ||
| messageId?: string; | ||
| }; | ||
| export interface AssistantTransport { | ||
| send(request: AssistantTransportSendRequest, signal: AssistantCancellationSignal): AsyncIterable<AssistantTransportEvent>; | ||
| submitFeedback(request: AssistantTransportFeedbackRequest): Promise<void>; | ||
| destroy?(): void; | ||
| } | ||
| export type AssistantLifecycleEvent = { | ||
| type: 'completed'; | ||
| threadId?: string; | ||
| messageId?: string; | ||
| metadata: AssistantLifecycleMetadata; | ||
| } | { | ||
| type: 'errored'; | ||
| error: AssistantErrorSnapshot; | ||
| metadata: AssistantLifecycleMetadata; | ||
| } | { | ||
| type: 'feedback-submitted'; | ||
| messageId: string; | ||
| feedback: AssistantFeedback; | ||
| metadata: AssistantLifecycleMetadata; | ||
| } | { | ||
| type: 'new-thread'; | ||
| metadata: AssistantLifecycleMetadata; | ||
| }; | ||
| export type AssistantMetadata = { | ||
| readonly surface: AssistantSurface; | ||
| readonly entryPoint: string; | ||
| readonly loaderVersion?: string; | ||
| }; | ||
| export type AssistantLifecycleMetadata = AssistantMetadata & { | ||
| readonly coreVersion: string; | ||
| }; | ||
| export type AssistantCoreOptions = { | ||
| readonly transport: AssistantTransport; | ||
| readonly storage?: AssistantStorageAdapter; | ||
| readonly metadata: AssistantMetadata; | ||
| readonly context?: AssistantContext; | ||
| readonly createId?: () => string; | ||
| readonly onEvent?: (event: AssistantLifecycleEvent) => void; | ||
| }; | ||
| export type AssistantSendInput = { | ||
| readonly content: string; | ||
| readonly context?: AssistantContext; | ||
| readonly surface?: AssistantSurface; | ||
| readonly entryPoint?: string; | ||
| }; | ||
| export type AssistantFeedbackInput = { | ||
| readonly messageId: string; | ||
| readonly feedback: AssistantFeedback; | ||
| }; | ||
| export interface AssistantCore { | ||
| send(input: AssistantSendInput): Promise<AssistantSnapshot>; | ||
| abort(): void; | ||
| retry(): Promise<AssistantSnapshot>; | ||
| newThread(): AssistantSnapshot; | ||
| setContext(context?: AssistantContext): void; | ||
| submitFeedback(input: AssistantFeedbackInput): Promise<void>; | ||
| getSnapshot(): AssistantSnapshot; | ||
| subscribe(listener: (snapshot: AssistantSnapshot) => void): () => void; | ||
| destroy(): void; | ||
| } |
| export {}; |
+93
| Copyright (c) 2022 Mintlify, Inc. | ||
| Elastic License 2.0 | ||
| ## Acceptance | ||
| By using the software, you agree to all of the terms and conditions below. | ||
| ## Copyright License | ||
| The licensor grants you a non-exclusive, royalty-free, worldwide, | ||
| non-sublicensable, non-transferable license to use, copy, distribute, make | ||
| available, and prepare derivative works of the software, in each case subject to | ||
| the limitations and conditions below. | ||
| ## Limitations | ||
| You may not provide the software to third parties as a hosted or managed | ||
| service, where the service provides users with access to any substantial set of | ||
| the features or functionality of the software. | ||
| You may not move, change, disable, or circumvent the license key functionality | ||
| in the software, and you may not remove or obscure any functionality in the | ||
| software that is protected by the license key. | ||
| You may not alter, remove, or obscure any licensing, copyright, or other notices | ||
| of the licensor in the software. Any use of the licensor’s trademarks is subject | ||
| to applicable law. | ||
| ## Patents | ||
| The licensor grants you a license, under any patent claims the licensor can | ||
| license, or becomes able to license, to make, have made, use, sell, offer for | ||
| sale, import and have imported the software, in each case subject to the | ||
| limitations and conditions in this license. This license does not cover any | ||
| patent claims that you cause to be infringed by modifications or additions to | ||
| the software. If you or your company make any written claim that the software | ||
| infringes or contributes to infringement of any patent, your patent license for | ||
| the software granted under these terms ends immediately. If your company makes | ||
| such a claim, your patent license ends immediately for work on behalf of your | ||
| company. | ||
| ## Notices | ||
| You must ensure that anyone who gets a copy of any part of the software from you | ||
| also gets a copy of these terms. | ||
| If you modify the software, you must include in any modified copies of the | ||
| software prominent notices stating that you have modified the software. | ||
| ## No Other Rights | ||
| These terms do not imply any licenses other than those expressly granted in | ||
| these terms. | ||
| ## Termination | ||
| If you use the software in violation of these terms, such use is not licensed, | ||
| and your licenses will automatically terminate. If the licensor provides you | ||
| with a notice of your violation, and you cease all violation of this license no | ||
| later than 30 days after you receive that notice, your licenses will be | ||
| reinstated retroactively. However, if you violate these terms after such | ||
| reinstatement, any additional violation of these terms will cause your licenses | ||
| to terminate automatically and permanently. | ||
| ## No Liability | ||
| _As far as the law allows, the software comes as is, without any warranty or | ||
| condition, and the licensor will not be liable to you for any damages arising | ||
| out of these terms or the use or nature of the software, under any kind of | ||
| legal claim._ | ||
| ## Definitions | ||
| The **licensor** is the entity offering these terms, and the **software** is the | ||
| software the licensor makes available under these terms, including any portion | ||
| of it. | ||
| **you** refers to the individual or entity agreeing to these terms. | ||
| **your company** is any legal entity, sole proprietorship, or other kind of | ||
| organization that you work for, plus all organizations that have control over, | ||
| are under the control of, or are under common control with that | ||
| organization. **control** means ownership of substantially all the assets of an | ||
| entity, or the power to direct its management and policies by vote, contract, or | ||
| otherwise. Control can be direct or indirect. | ||
| **your licenses** are all the licenses granted to you for the software under | ||
| these terms. | ||
| **use** means anything you do with the software requiring one of your licenses. | ||
| **trademark** means trademarks, service marks, and similar rights. |
+6
-5
| { | ||
| "name": "@mintlify/assistant-core", | ||
| "version": "0.0.5", | ||
| "version": "0.0.6", | ||
| "description": "Framework-independent state and transport core for Mintlify Assistant", | ||
@@ -17,4 +17,3 @@ "type": "module", | ||
| "files": [ | ||
| "dist/**/*.d.ts", | ||
| "dist/**/*.js", | ||
| "dist", | ||
| "examples" | ||
@@ -35,3 +34,4 @@ ], | ||
| "clean:all": "rimraf node_modules .eslintcache && yarn clean:build", | ||
| "watch": "tsc --project tsconfig.json --watch", | ||
| "prepack": "yarn build", | ||
| "watch": "tsc --project tsconfig.json --watch --preserveWatchOutput", | ||
| "test": "vitest run", | ||
@@ -54,3 +54,4 @@ "type": "tsc --noEmit", | ||
| "vitest": "2.1.9" | ||
| } | ||
| }, | ||
| "gitHead": "2ab3d2f9c7fc427013d7da3d10715baf6ce32647" | ||
| } |
Unpublished package
Supply chain riskPackage version was not found on the registry. It may exist on a different registry and need to be configured to pull from that registry.
Unpublished package
Supply chain riskPackage version was not found on the registry. It may exist on a different registry and need to be configured to pull from that registry.
54726
467.17%17
325%1054
1009.47%