7461 lines
286 KiB
JavaScript
7461 lines
286 KiB
JavaScript
/*
|
||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||
if you want to view the source, please visit the github repository of this plugin
|
||
*/
|
||
|
||
var __defProp = Object.defineProperty;
|
||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||
var __export = (target, all) => {
|
||
for (var name in all)
|
||
__defProp(target, name, { get: all[name], enumerable: true });
|
||
};
|
||
var __copyProps = (to, from, except, desc) => {
|
||
if (from && typeof from === "object" || typeof from === "function") {
|
||
for (let key of __getOwnPropNames(from))
|
||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||
}
|
||
return to;
|
||
};
|
||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||
|
||
// main.ts
|
||
var main_exports = {};
|
||
__export(main_exports, {
|
||
default: () => MemosSyncPlugin
|
||
});
|
||
module.exports = __toCommonJS(main_exports);
|
||
var import_obsidian6 = require("obsidian");
|
||
|
||
// src/models/settings.ts
|
||
var DEFAULT_SETTINGS = {
|
||
memosApiUrl: "",
|
||
memosAccessToken: "",
|
||
syncDirectory: "memos",
|
||
syncFrequency: "manual",
|
||
autoSyncInterval: 30,
|
||
syncLimit: 1e3,
|
||
ai: {
|
||
enabled: false,
|
||
modelType: "openai",
|
||
apiKey: "",
|
||
modelName: "gpt-4o",
|
||
customModelName: "",
|
||
openaiBaseUrl: "https://api.openai.com/v1",
|
||
ollamaBaseUrl: "http://localhost:11434",
|
||
weeklyDigest: true,
|
||
autoTags: true,
|
||
intelligentSummary: true,
|
||
summaryLanguage: "zh"
|
||
}
|
||
};
|
||
|
||
// src/ui/settings-tab.ts
|
||
var import_obsidian2 = require("obsidian");
|
||
|
||
// node_modules/@google/generative-ai/dist/index.mjs
|
||
var SchemaType;
|
||
(function(SchemaType2) {
|
||
SchemaType2["STRING"] = "string";
|
||
SchemaType2["NUMBER"] = "number";
|
||
SchemaType2["INTEGER"] = "integer";
|
||
SchemaType2["BOOLEAN"] = "boolean";
|
||
SchemaType2["ARRAY"] = "array";
|
||
SchemaType2["OBJECT"] = "object";
|
||
})(SchemaType || (SchemaType = {}));
|
||
var ExecutableCodeLanguage;
|
||
(function(ExecutableCodeLanguage2) {
|
||
ExecutableCodeLanguage2["LANGUAGE_UNSPECIFIED"] = "language_unspecified";
|
||
ExecutableCodeLanguage2["PYTHON"] = "python";
|
||
})(ExecutableCodeLanguage || (ExecutableCodeLanguage = {}));
|
||
var Outcome;
|
||
(function(Outcome2) {
|
||
Outcome2["OUTCOME_UNSPECIFIED"] = "outcome_unspecified";
|
||
Outcome2["OUTCOME_OK"] = "outcome_ok";
|
||
Outcome2["OUTCOME_FAILED"] = "outcome_failed";
|
||
Outcome2["OUTCOME_DEADLINE_EXCEEDED"] = "outcome_deadline_exceeded";
|
||
})(Outcome || (Outcome = {}));
|
||
var POSSIBLE_ROLES = ["user", "model", "function", "system"];
|
||
var HarmCategory;
|
||
(function(HarmCategory2) {
|
||
HarmCategory2["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED";
|
||
HarmCategory2["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH";
|
||
HarmCategory2["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT";
|
||
HarmCategory2["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT";
|
||
HarmCategory2["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT";
|
||
})(HarmCategory || (HarmCategory = {}));
|
||
var HarmBlockThreshold;
|
||
(function(HarmBlockThreshold2) {
|
||
HarmBlockThreshold2["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED";
|
||
HarmBlockThreshold2["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE";
|
||
HarmBlockThreshold2["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE";
|
||
HarmBlockThreshold2["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH";
|
||
HarmBlockThreshold2["BLOCK_NONE"] = "BLOCK_NONE";
|
||
})(HarmBlockThreshold || (HarmBlockThreshold = {}));
|
||
var HarmProbability;
|
||
(function(HarmProbability2) {
|
||
HarmProbability2["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED";
|
||
HarmProbability2["NEGLIGIBLE"] = "NEGLIGIBLE";
|
||
HarmProbability2["LOW"] = "LOW";
|
||
HarmProbability2["MEDIUM"] = "MEDIUM";
|
||
HarmProbability2["HIGH"] = "HIGH";
|
||
})(HarmProbability || (HarmProbability = {}));
|
||
var BlockReason;
|
||
(function(BlockReason2) {
|
||
BlockReason2["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED";
|
||
BlockReason2["SAFETY"] = "SAFETY";
|
||
BlockReason2["OTHER"] = "OTHER";
|
||
})(BlockReason || (BlockReason = {}));
|
||
var FinishReason;
|
||
(function(FinishReason2) {
|
||
FinishReason2["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED";
|
||
FinishReason2["STOP"] = "STOP";
|
||
FinishReason2["MAX_TOKENS"] = "MAX_TOKENS";
|
||
FinishReason2["SAFETY"] = "SAFETY";
|
||
FinishReason2["RECITATION"] = "RECITATION";
|
||
FinishReason2["LANGUAGE"] = "LANGUAGE";
|
||
FinishReason2["OTHER"] = "OTHER";
|
||
})(FinishReason || (FinishReason = {}));
|
||
var TaskType;
|
||
(function(TaskType2) {
|
||
TaskType2["TASK_TYPE_UNSPECIFIED"] = "TASK_TYPE_UNSPECIFIED";
|
||
TaskType2["RETRIEVAL_QUERY"] = "RETRIEVAL_QUERY";
|
||
TaskType2["RETRIEVAL_DOCUMENT"] = "RETRIEVAL_DOCUMENT";
|
||
TaskType2["SEMANTIC_SIMILARITY"] = "SEMANTIC_SIMILARITY";
|
||
TaskType2["CLASSIFICATION"] = "CLASSIFICATION";
|
||
TaskType2["CLUSTERING"] = "CLUSTERING";
|
||
})(TaskType || (TaskType = {}));
|
||
var FunctionCallingMode;
|
||
(function(FunctionCallingMode2) {
|
||
FunctionCallingMode2["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED";
|
||
FunctionCallingMode2["AUTO"] = "AUTO";
|
||
FunctionCallingMode2["ANY"] = "ANY";
|
||
FunctionCallingMode2["NONE"] = "NONE";
|
||
})(FunctionCallingMode || (FunctionCallingMode = {}));
|
||
var DynamicRetrievalMode;
|
||
(function(DynamicRetrievalMode2) {
|
||
DynamicRetrievalMode2["MODE_UNSPECIFIED"] = "MODE_UNSPECIFIED";
|
||
DynamicRetrievalMode2["MODE_DYNAMIC"] = "MODE_DYNAMIC";
|
||
})(DynamicRetrievalMode || (DynamicRetrievalMode = {}));
|
||
var GoogleGenerativeAIError = class extends Error {
|
||
constructor(message) {
|
||
super(`[GoogleGenerativeAI Error]: ${message}`);
|
||
}
|
||
};
|
||
var GoogleGenerativeAIResponseError = class extends GoogleGenerativeAIError {
|
||
constructor(message, response) {
|
||
super(message);
|
||
this.response = response;
|
||
}
|
||
};
|
||
var GoogleGenerativeAIFetchError = class extends GoogleGenerativeAIError {
|
||
constructor(message, status, statusText, errorDetails) {
|
||
super(message);
|
||
this.status = status;
|
||
this.statusText = statusText;
|
||
this.errorDetails = errorDetails;
|
||
}
|
||
};
|
||
var GoogleGenerativeAIRequestInputError = class extends GoogleGenerativeAIError {
|
||
};
|
||
var DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com";
|
||
var DEFAULT_API_VERSION = "v1beta";
|
||
var PACKAGE_VERSION = "0.21.0";
|
||
var PACKAGE_LOG_HEADER = "genai-js";
|
||
var Task;
|
||
(function(Task2) {
|
||
Task2["GENERATE_CONTENT"] = "generateContent";
|
||
Task2["STREAM_GENERATE_CONTENT"] = "streamGenerateContent";
|
||
Task2["COUNT_TOKENS"] = "countTokens";
|
||
Task2["EMBED_CONTENT"] = "embedContent";
|
||
Task2["BATCH_EMBED_CONTENTS"] = "batchEmbedContents";
|
||
})(Task || (Task = {}));
|
||
var RequestUrl = class {
|
||
constructor(model, task, apiKey, stream, requestOptions) {
|
||
this.model = model;
|
||
this.task = task;
|
||
this.apiKey = apiKey;
|
||
this.stream = stream;
|
||
this.requestOptions = requestOptions;
|
||
}
|
||
toString() {
|
||
var _a2, _b;
|
||
const apiVersion = ((_a2 = this.requestOptions) === null || _a2 === void 0 ? void 0 : _a2.apiVersion) || DEFAULT_API_VERSION;
|
||
const baseUrl = ((_b = this.requestOptions) === null || _b === void 0 ? void 0 : _b.baseUrl) || DEFAULT_BASE_URL;
|
||
let url = `${baseUrl}/${apiVersion}/${this.model}:${this.task}`;
|
||
if (this.stream) {
|
||
url += "?alt=sse";
|
||
}
|
||
return url;
|
||
}
|
||
};
|
||
function getClientHeaders(requestOptions) {
|
||
const clientHeaders = [];
|
||
if (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.apiClient) {
|
||
clientHeaders.push(requestOptions.apiClient);
|
||
}
|
||
clientHeaders.push(`${PACKAGE_LOG_HEADER}/${PACKAGE_VERSION}`);
|
||
return clientHeaders.join(" ");
|
||
}
|
||
async function getHeaders(url) {
|
||
var _a2;
|
||
const headers = new Headers();
|
||
headers.append("Content-Type", "application/json");
|
||
headers.append("x-goog-api-client", getClientHeaders(url.requestOptions));
|
||
headers.append("x-goog-api-key", url.apiKey);
|
||
let customHeaders = (_a2 = url.requestOptions) === null || _a2 === void 0 ? void 0 : _a2.customHeaders;
|
||
if (customHeaders) {
|
||
if (!(customHeaders instanceof Headers)) {
|
||
try {
|
||
customHeaders = new Headers(customHeaders);
|
||
} catch (e) {
|
||
throw new GoogleGenerativeAIRequestInputError(`unable to convert customHeaders value ${JSON.stringify(customHeaders)} to Headers: ${e.message}`);
|
||
}
|
||
}
|
||
for (const [headerName, headerValue] of customHeaders.entries()) {
|
||
if (headerName === "x-goog-api-key") {
|
||
throw new GoogleGenerativeAIRequestInputError(`Cannot set reserved header name ${headerName}`);
|
||
} else if (headerName === "x-goog-api-client") {
|
||
throw new GoogleGenerativeAIRequestInputError(`Header name ${headerName} can only be set using the apiClient field`);
|
||
}
|
||
headers.append(headerName, headerValue);
|
||
}
|
||
}
|
||
return headers;
|
||
}
|
||
async function constructModelRequest(model, task, apiKey, stream, body, requestOptions) {
|
||
const url = new RequestUrl(model, task, apiKey, stream, requestOptions);
|
||
return {
|
||
url: url.toString(),
|
||
fetchOptions: Object.assign(Object.assign({}, buildFetchOptions(requestOptions)), { method: "POST", headers: await getHeaders(url), body })
|
||
};
|
||
}
|
||
async function makeModelRequest(model, task, apiKey, stream, body, requestOptions = {}, fetchFn = fetch) {
|
||
const { url, fetchOptions } = await constructModelRequest(model, task, apiKey, stream, body, requestOptions);
|
||
return makeRequest(url, fetchOptions, fetchFn);
|
||
}
|
||
async function makeRequest(url, fetchOptions, fetchFn = fetch) {
|
||
let response;
|
||
try {
|
||
response = await fetchFn(url, fetchOptions);
|
||
} catch (e) {
|
||
handleResponseError(e, url);
|
||
}
|
||
if (!response.ok) {
|
||
await handleResponseNotOk(response, url);
|
||
}
|
||
return response;
|
||
}
|
||
function handleResponseError(e, url) {
|
||
let err = e;
|
||
if (!(e instanceof GoogleGenerativeAIFetchError || e instanceof GoogleGenerativeAIRequestInputError)) {
|
||
err = new GoogleGenerativeAIError(`Error fetching from ${url.toString()}: ${e.message}`);
|
||
err.stack = e.stack;
|
||
}
|
||
throw err;
|
||
}
|
||
async function handleResponseNotOk(response, url) {
|
||
let message = "";
|
||
let errorDetails;
|
||
try {
|
||
const json = await response.json();
|
||
message = json.error.message;
|
||
if (json.error.details) {
|
||
message += ` ${JSON.stringify(json.error.details)}`;
|
||
errorDetails = json.error.details;
|
||
}
|
||
} catch (e) {
|
||
}
|
||
throw new GoogleGenerativeAIFetchError(`Error fetching from ${url.toString()}: [${response.status} ${response.statusText}] ${message}`, response.status, response.statusText, errorDetails);
|
||
}
|
||
function buildFetchOptions(requestOptions) {
|
||
const fetchOptions = {};
|
||
if ((requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.signal) !== void 0 || (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.timeout) >= 0) {
|
||
const controller = new AbortController();
|
||
if ((requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.timeout) >= 0) {
|
||
setTimeout(() => controller.abort(), requestOptions.timeout);
|
||
}
|
||
if (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.signal) {
|
||
requestOptions.signal.addEventListener("abort", () => {
|
||
controller.abort();
|
||
});
|
||
}
|
||
fetchOptions.signal = controller.signal;
|
||
}
|
||
return fetchOptions;
|
||
}
|
||
function addHelpers(response) {
|
||
response.text = () => {
|
||
if (response.candidates && response.candidates.length > 0) {
|
||
if (response.candidates.length > 1) {
|
||
console.warn(`This response had ${response.candidates.length} candidates. Returning text from the first candidate only. Access response.candidates directly to use the other candidates.`);
|
||
}
|
||
if (hadBadFinishReason(response.candidates[0])) {
|
||
throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
|
||
}
|
||
return getText(response);
|
||
} else if (response.promptFeedback) {
|
||
throw new GoogleGenerativeAIResponseError(`Text not available. ${formatBlockErrorMessage(response)}`, response);
|
||
}
|
||
return "";
|
||
};
|
||
response.functionCall = () => {
|
||
if (response.candidates && response.candidates.length > 0) {
|
||
if (response.candidates.length > 1) {
|
||
console.warn(`This response had ${response.candidates.length} candidates. Returning function calls from the first candidate only. Access response.candidates directly to use the other candidates.`);
|
||
}
|
||
if (hadBadFinishReason(response.candidates[0])) {
|
||
throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
|
||
}
|
||
console.warn(`response.functionCall() is deprecated. Use response.functionCalls() instead.`);
|
||
return getFunctionCalls(response)[0];
|
||
} else if (response.promptFeedback) {
|
||
throw new GoogleGenerativeAIResponseError(`Function call not available. ${formatBlockErrorMessage(response)}`, response);
|
||
}
|
||
return void 0;
|
||
};
|
||
response.functionCalls = () => {
|
||
if (response.candidates && response.candidates.length > 0) {
|
||
if (response.candidates.length > 1) {
|
||
console.warn(`This response had ${response.candidates.length} candidates. Returning function calls from the first candidate only. Access response.candidates directly to use the other candidates.`);
|
||
}
|
||
if (hadBadFinishReason(response.candidates[0])) {
|
||
throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
|
||
}
|
||
return getFunctionCalls(response);
|
||
} else if (response.promptFeedback) {
|
||
throw new GoogleGenerativeAIResponseError(`Function call not available. ${formatBlockErrorMessage(response)}`, response);
|
||
}
|
||
return void 0;
|
||
};
|
||
return response;
|
||
}
|
||
function getText(response) {
|
||
var _a2, _b, _c, _d;
|
||
const textStrings = [];
|
||
if ((_b = (_a2 = response.candidates) === null || _a2 === void 0 ? void 0 : _a2[0].content) === null || _b === void 0 ? void 0 : _b.parts) {
|
||
for (const part of (_d = (_c = response.candidates) === null || _c === void 0 ? void 0 : _c[0].content) === null || _d === void 0 ? void 0 : _d.parts) {
|
||
if (part.text) {
|
||
textStrings.push(part.text);
|
||
}
|
||
if (part.executableCode) {
|
||
textStrings.push("\n```" + part.executableCode.language + "\n" + part.executableCode.code + "\n```\n");
|
||
}
|
||
if (part.codeExecutionResult) {
|
||
textStrings.push("\n```\n" + part.codeExecutionResult.output + "\n```\n");
|
||
}
|
||
}
|
||
}
|
||
if (textStrings.length > 0) {
|
||
return textStrings.join("");
|
||
} else {
|
||
return "";
|
||
}
|
||
}
|
||
function getFunctionCalls(response) {
|
||
var _a2, _b, _c, _d;
|
||
const functionCalls = [];
|
||
if ((_b = (_a2 = response.candidates) === null || _a2 === void 0 ? void 0 : _a2[0].content) === null || _b === void 0 ? void 0 : _b.parts) {
|
||
for (const part of (_d = (_c = response.candidates) === null || _c === void 0 ? void 0 : _c[0].content) === null || _d === void 0 ? void 0 : _d.parts) {
|
||
if (part.functionCall) {
|
||
functionCalls.push(part.functionCall);
|
||
}
|
||
}
|
||
}
|
||
if (functionCalls.length > 0) {
|
||
return functionCalls;
|
||
} else {
|
||
return void 0;
|
||
}
|
||
}
|
||
var badFinishReasons = [
|
||
FinishReason.RECITATION,
|
||
FinishReason.SAFETY,
|
||
FinishReason.LANGUAGE
|
||
];
|
||
function hadBadFinishReason(candidate) {
|
||
return !!candidate.finishReason && badFinishReasons.includes(candidate.finishReason);
|
||
}
|
||
function formatBlockErrorMessage(response) {
|
||
var _a2, _b, _c;
|
||
let message = "";
|
||
if ((!response.candidates || response.candidates.length === 0) && response.promptFeedback) {
|
||
message += "Response was blocked";
|
||
if ((_a2 = response.promptFeedback) === null || _a2 === void 0 ? void 0 : _a2.blockReason) {
|
||
message += ` due to ${response.promptFeedback.blockReason}`;
|
||
}
|
||
if ((_b = response.promptFeedback) === null || _b === void 0 ? void 0 : _b.blockReasonMessage) {
|
||
message += `: ${response.promptFeedback.blockReasonMessage}`;
|
||
}
|
||
} else if ((_c = response.candidates) === null || _c === void 0 ? void 0 : _c[0]) {
|
||
const firstCandidate = response.candidates[0];
|
||
if (hadBadFinishReason(firstCandidate)) {
|
||
message += `Candidate was blocked due to ${firstCandidate.finishReason}`;
|
||
if (firstCandidate.finishMessage) {
|
||
message += `: ${firstCandidate.finishMessage}`;
|
||
}
|
||
}
|
||
}
|
||
return message;
|
||
}
|
||
function __await(v) {
|
||
return this instanceof __await ? (this.v = v, this) : new __await(v);
|
||
}
|
||
function __asyncGenerator(thisArg, _arguments, generator) {
|
||
if (!Symbol.asyncIterator)
|
||
throw new TypeError("Symbol.asyncIterator is not defined.");
|
||
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
||
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
|
||
return this;
|
||
}, i;
|
||
function verb(n) {
|
||
if (g[n])
|
||
i[n] = function(v) {
|
||
return new Promise(function(a, b) {
|
||
q.push([n, v, a, b]) > 1 || resume(n, v);
|
||
});
|
||
};
|
||
}
|
||
function resume(n, v) {
|
||
try {
|
||
step(g[n](v));
|
||
} catch (e) {
|
||
settle(q[0][3], e);
|
||
}
|
||
}
|
||
function step(r) {
|
||
r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
|
||
}
|
||
function fulfill(value) {
|
||
resume("next", value);
|
||
}
|
||
function reject(value) {
|
||
resume("throw", value);
|
||
}
|
||
function settle(f, v) {
|
||
if (f(v), q.shift(), q.length)
|
||
resume(q[0][0], q[0][1]);
|
||
}
|
||
}
|
||
var responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/;
|
||
function processStream(response) {
|
||
const inputStream = response.body.pipeThrough(new TextDecoderStream("utf8", { fatal: true }));
|
||
const responseStream = getResponseStream(inputStream);
|
||
const [stream1, stream2] = responseStream.tee();
|
||
return {
|
||
stream: generateResponseSequence(stream1),
|
||
response: getResponsePromise(stream2)
|
||
};
|
||
}
|
||
async function getResponsePromise(stream) {
|
||
const allResponses = [];
|
||
const reader = stream.getReader();
|
||
while (true) {
|
||
const { done, value } = await reader.read();
|
||
if (done) {
|
||
return addHelpers(aggregateResponses(allResponses));
|
||
}
|
||
allResponses.push(value);
|
||
}
|
||
}
|
||
function generateResponseSequence(stream) {
|
||
return __asyncGenerator(this, arguments, function* generateResponseSequence_1() {
|
||
const reader = stream.getReader();
|
||
while (true) {
|
||
const { value, done } = yield __await(reader.read());
|
||
if (done) {
|
||
break;
|
||
}
|
||
yield yield __await(addHelpers(value));
|
||
}
|
||
});
|
||
}
|
||
function getResponseStream(inputStream) {
|
||
const reader = inputStream.getReader();
|
||
const stream = new ReadableStream({
|
||
start(controller) {
|
||
let currentText = "";
|
||
return pump();
|
||
function pump() {
|
||
return reader.read().then(({ value, done }) => {
|
||
if (done) {
|
||
if (currentText.trim()) {
|
||
controller.error(new GoogleGenerativeAIError("Failed to parse stream"));
|
||
return;
|
||
}
|
||
controller.close();
|
||
return;
|
||
}
|
||
currentText += value;
|
||
let match = currentText.match(responseLineRE);
|
||
let parsedResponse;
|
||
while (match) {
|
||
try {
|
||
parsedResponse = JSON.parse(match[1]);
|
||
} catch (e) {
|
||
controller.error(new GoogleGenerativeAIError(`Error parsing JSON response: "${match[1]}"`));
|
||
return;
|
||
}
|
||
controller.enqueue(parsedResponse);
|
||
currentText = currentText.substring(match[0].length);
|
||
match = currentText.match(responseLineRE);
|
||
}
|
||
return pump();
|
||
});
|
||
}
|
||
}
|
||
});
|
||
return stream;
|
||
}
|
||
function aggregateResponses(responses) {
|
||
const lastResponse = responses[responses.length - 1];
|
||
const aggregatedResponse = {
|
||
promptFeedback: lastResponse === null || lastResponse === void 0 ? void 0 : lastResponse.promptFeedback
|
||
};
|
||
for (const response of responses) {
|
||
if (response.candidates) {
|
||
for (const candidate of response.candidates) {
|
||
const i = candidate.index;
|
||
if (!aggregatedResponse.candidates) {
|
||
aggregatedResponse.candidates = [];
|
||
}
|
||
if (!aggregatedResponse.candidates[i]) {
|
||
aggregatedResponse.candidates[i] = {
|
||
index: candidate.index
|
||
};
|
||
}
|
||
aggregatedResponse.candidates[i].citationMetadata = candidate.citationMetadata;
|
||
aggregatedResponse.candidates[i].groundingMetadata = candidate.groundingMetadata;
|
||
aggregatedResponse.candidates[i].finishReason = candidate.finishReason;
|
||
aggregatedResponse.candidates[i].finishMessage = candidate.finishMessage;
|
||
aggregatedResponse.candidates[i].safetyRatings = candidate.safetyRatings;
|
||
if (candidate.content && candidate.content.parts) {
|
||
if (!aggregatedResponse.candidates[i].content) {
|
||
aggregatedResponse.candidates[i].content = {
|
||
role: candidate.content.role || "user",
|
||
parts: []
|
||
};
|
||
}
|
||
const newPart = {};
|
||
for (const part of candidate.content.parts) {
|
||
if (part.text) {
|
||
newPart.text = part.text;
|
||
}
|
||
if (part.functionCall) {
|
||
newPart.functionCall = part.functionCall;
|
||
}
|
||
if (part.executableCode) {
|
||
newPart.executableCode = part.executableCode;
|
||
}
|
||
if (part.codeExecutionResult) {
|
||
newPart.codeExecutionResult = part.codeExecutionResult;
|
||
}
|
||
if (Object.keys(newPart).length === 0) {
|
||
newPart.text = "";
|
||
}
|
||
aggregatedResponse.candidates[i].content.parts.push(newPart);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (response.usageMetadata) {
|
||
aggregatedResponse.usageMetadata = response.usageMetadata;
|
||
}
|
||
}
|
||
return aggregatedResponse;
|
||
}
|
||
async function generateContentStream(apiKey, model, params, requestOptions) {
|
||
const response = await makeModelRequest(
|
||
model,
|
||
Task.STREAM_GENERATE_CONTENT,
|
||
apiKey,
|
||
/* stream */
|
||
true,
|
||
JSON.stringify(params),
|
||
requestOptions
|
||
);
|
||
return processStream(response);
|
||
}
|
||
async function generateContent(apiKey, model, params, requestOptions) {
|
||
const response = await makeModelRequest(
|
||
model,
|
||
Task.GENERATE_CONTENT,
|
||
apiKey,
|
||
/* stream */
|
||
false,
|
||
JSON.stringify(params),
|
||
requestOptions
|
||
);
|
||
const responseJson = await response.json();
|
||
const enhancedResponse = addHelpers(responseJson);
|
||
return {
|
||
response: enhancedResponse
|
||
};
|
||
}
|
||
function formatSystemInstruction(input) {
|
||
if (input == null) {
|
||
return void 0;
|
||
} else if (typeof input === "string") {
|
||
return { role: "system", parts: [{ text: input }] };
|
||
} else if (input.text) {
|
||
return { role: "system", parts: [input] };
|
||
} else if (input.parts) {
|
||
if (!input.role) {
|
||
return { role: "system", parts: input.parts };
|
||
} else {
|
||
return input;
|
||
}
|
||
}
|
||
}
|
||
function formatNewContent(request) {
|
||
let newParts = [];
|
||
if (typeof request === "string") {
|
||
newParts = [{ text: request }];
|
||
} else {
|
||
for (const partOrString of request) {
|
||
if (typeof partOrString === "string") {
|
||
newParts.push({ text: partOrString });
|
||
} else {
|
||
newParts.push(partOrString);
|
||
}
|
||
}
|
||
}
|
||
return assignRoleToPartsAndValidateSendMessageRequest(newParts);
|
||
}
|
||
function assignRoleToPartsAndValidateSendMessageRequest(parts) {
|
||
const userContent = { role: "user", parts: [] };
|
||
const functionContent = { role: "function", parts: [] };
|
||
let hasUserContent = false;
|
||
let hasFunctionContent = false;
|
||
for (const part of parts) {
|
||
if ("functionResponse" in part) {
|
||
functionContent.parts.push(part);
|
||
hasFunctionContent = true;
|
||
} else {
|
||
userContent.parts.push(part);
|
||
hasUserContent = true;
|
||
}
|
||
}
|
||
if (hasUserContent && hasFunctionContent) {
|
||
throw new GoogleGenerativeAIError("Within a single message, FunctionResponse cannot be mixed with other type of part in the request for sending chat message.");
|
||
}
|
||
if (!hasUserContent && !hasFunctionContent) {
|
||
throw new GoogleGenerativeAIError("No content is provided for sending chat message.");
|
||
}
|
||
if (hasUserContent) {
|
||
return userContent;
|
||
}
|
||
return functionContent;
|
||
}
|
||
function formatCountTokensInput(params, modelParams) {
|
||
var _a2;
|
||
let formattedGenerateContentRequest = {
|
||
model: modelParams === null || modelParams === void 0 ? void 0 : modelParams.model,
|
||
generationConfig: modelParams === null || modelParams === void 0 ? void 0 : modelParams.generationConfig,
|
||
safetySettings: modelParams === null || modelParams === void 0 ? void 0 : modelParams.safetySettings,
|
||
tools: modelParams === null || modelParams === void 0 ? void 0 : modelParams.tools,
|
||
toolConfig: modelParams === null || modelParams === void 0 ? void 0 : modelParams.toolConfig,
|
||
systemInstruction: modelParams === null || modelParams === void 0 ? void 0 : modelParams.systemInstruction,
|
||
cachedContent: (_a2 = modelParams === null || modelParams === void 0 ? void 0 : modelParams.cachedContent) === null || _a2 === void 0 ? void 0 : _a2.name,
|
||
contents: []
|
||
};
|
||
const containsGenerateContentRequest = params.generateContentRequest != null;
|
||
if (params.contents) {
|
||
if (containsGenerateContentRequest) {
|
||
throw new GoogleGenerativeAIRequestInputError("CountTokensRequest must have one of contents or generateContentRequest, not both.");
|
||
}
|
||
formattedGenerateContentRequest.contents = params.contents;
|
||
} else if (containsGenerateContentRequest) {
|
||
formattedGenerateContentRequest = Object.assign(Object.assign({}, formattedGenerateContentRequest), params.generateContentRequest);
|
||
} else {
|
||
const content = formatNewContent(params);
|
||
formattedGenerateContentRequest.contents = [content];
|
||
}
|
||
return { generateContentRequest: formattedGenerateContentRequest };
|
||
}
|
||
function formatGenerateContentInput(params) {
|
||
let formattedRequest;
|
||
if (params.contents) {
|
||
formattedRequest = params;
|
||
} else {
|
||
const content = formatNewContent(params);
|
||
formattedRequest = { contents: [content] };
|
||
}
|
||
if (params.systemInstruction) {
|
||
formattedRequest.systemInstruction = formatSystemInstruction(params.systemInstruction);
|
||
}
|
||
return formattedRequest;
|
||
}
|
||
function formatEmbedContentInput(params) {
|
||
if (typeof params === "string" || Array.isArray(params)) {
|
||
const content = formatNewContent(params);
|
||
return { content };
|
||
}
|
||
return params;
|
||
}
|
||
var VALID_PART_FIELDS = [
|
||
"text",
|
||
"inlineData",
|
||
"functionCall",
|
||
"functionResponse",
|
||
"executableCode",
|
||
"codeExecutionResult"
|
||
];
|
||
var VALID_PARTS_PER_ROLE = {
|
||
user: ["text", "inlineData"],
|
||
function: ["functionResponse"],
|
||
model: ["text", "functionCall", "executableCode", "codeExecutionResult"],
|
||
// System instructions shouldn't be in history anyway.
|
||
system: ["text"]
|
||
};
|
||
function validateChatHistory(history) {
|
||
let prevContent = false;
|
||
for (const currContent of history) {
|
||
const { role, parts } = currContent;
|
||
if (!prevContent && role !== "user") {
|
||
throw new GoogleGenerativeAIError(`First content should be with role 'user', got ${role}`);
|
||
}
|
||
if (!POSSIBLE_ROLES.includes(role)) {
|
||
throw new GoogleGenerativeAIError(`Each item should include role field. Got ${role} but valid roles are: ${JSON.stringify(POSSIBLE_ROLES)}`);
|
||
}
|
||
if (!Array.isArray(parts)) {
|
||
throw new GoogleGenerativeAIError("Content should have 'parts' property with an array of Parts");
|
||
}
|
||
if (parts.length === 0) {
|
||
throw new GoogleGenerativeAIError("Each Content should have at least one part");
|
||
}
|
||
const countFields = {
|
||
text: 0,
|
||
inlineData: 0,
|
||
functionCall: 0,
|
||
functionResponse: 0,
|
||
fileData: 0,
|
||
executableCode: 0,
|
||
codeExecutionResult: 0
|
||
};
|
||
for (const part of parts) {
|
||
for (const key of VALID_PART_FIELDS) {
|
||
if (key in part) {
|
||
countFields[key] += 1;
|
||
}
|
||
}
|
||
}
|
||
const validParts = VALID_PARTS_PER_ROLE[role];
|
||
for (const key of VALID_PART_FIELDS) {
|
||
if (!validParts.includes(key) && countFields[key] > 0) {
|
||
throw new GoogleGenerativeAIError(`Content with role '${role}' can't contain '${key}' part`);
|
||
}
|
||
}
|
||
prevContent = true;
|
||
}
|
||
}
|
||
var SILENT_ERROR = "SILENT_ERROR";
|
||
var ChatSession = class {
|
||
constructor(apiKey, model, params, _requestOptions = {}) {
|
||
this.model = model;
|
||
this.params = params;
|
||
this._requestOptions = _requestOptions;
|
||
this._history = [];
|
||
this._sendPromise = Promise.resolve();
|
||
this._apiKey = apiKey;
|
||
if (params === null || params === void 0 ? void 0 : params.history) {
|
||
validateChatHistory(params.history);
|
||
this._history = params.history;
|
||
}
|
||
}
|
||
/**
|
||
* Gets the chat history so far. Blocked prompts are not added to history.
|
||
* Blocked candidates are not added to history, nor are the prompts that
|
||
* generated them.
|
||
*/
|
||
async getHistory() {
|
||
await this._sendPromise;
|
||
return this._history;
|
||
}
|
||
/**
|
||
* Sends a chat message and receives a non-streaming
|
||
* {@link GenerateContentResult}.
|
||
*
|
||
* Fields set in the optional {@link SingleRequestOptions} parameter will
|
||
* take precedence over the {@link RequestOptions} values provided to
|
||
* {@link GoogleGenerativeAI.getGenerativeModel }.
|
||
*/
|
||
async sendMessage(request, requestOptions = {}) {
|
||
var _a2, _b, _c, _d, _e, _f;
|
||
await this._sendPromise;
|
||
const newContent = formatNewContent(request);
|
||
const generateContentRequest = {
|
||
safetySettings: (_a2 = this.params) === null || _a2 === void 0 ? void 0 : _a2.safetySettings,
|
||
generationConfig: (_b = this.params) === null || _b === void 0 ? void 0 : _b.generationConfig,
|
||
tools: (_c = this.params) === null || _c === void 0 ? void 0 : _c.tools,
|
||
toolConfig: (_d = this.params) === null || _d === void 0 ? void 0 : _d.toolConfig,
|
||
systemInstruction: (_e = this.params) === null || _e === void 0 ? void 0 : _e.systemInstruction,
|
||
cachedContent: (_f = this.params) === null || _f === void 0 ? void 0 : _f.cachedContent,
|
||
contents: [...this._history, newContent]
|
||
};
|
||
const chatSessionRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
|
||
let finalResult;
|
||
this._sendPromise = this._sendPromise.then(() => generateContent(this._apiKey, this.model, generateContentRequest, chatSessionRequestOptions)).then((result) => {
|
||
var _a3;
|
||
if (result.response.candidates && result.response.candidates.length > 0) {
|
||
this._history.push(newContent);
|
||
const responseContent = Object.assign({
|
||
parts: [],
|
||
// Response seems to come back without a role set.
|
||
role: "model"
|
||
}, (_a3 = result.response.candidates) === null || _a3 === void 0 ? void 0 : _a3[0].content);
|
||
this._history.push(responseContent);
|
||
} else {
|
||
const blockErrorMessage = formatBlockErrorMessage(result.response);
|
||
if (blockErrorMessage) {
|
||
console.warn(`sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.`);
|
||
}
|
||
}
|
||
finalResult = result;
|
||
});
|
||
await this._sendPromise;
|
||
return finalResult;
|
||
}
|
||
/**
|
||
* Sends a chat message and receives the response as a
|
||
* {@link GenerateContentStreamResult} containing an iterable stream
|
||
* and a response promise.
|
||
*
|
||
* Fields set in the optional {@link SingleRequestOptions} parameter will
|
||
* take precedence over the {@link RequestOptions} values provided to
|
||
* {@link GoogleGenerativeAI.getGenerativeModel }.
|
||
*/
|
||
async sendMessageStream(request, requestOptions = {}) {
|
||
var _a2, _b, _c, _d, _e, _f;
|
||
await this._sendPromise;
|
||
const newContent = formatNewContent(request);
|
||
const generateContentRequest = {
|
||
safetySettings: (_a2 = this.params) === null || _a2 === void 0 ? void 0 : _a2.safetySettings,
|
||
generationConfig: (_b = this.params) === null || _b === void 0 ? void 0 : _b.generationConfig,
|
||
tools: (_c = this.params) === null || _c === void 0 ? void 0 : _c.tools,
|
||
toolConfig: (_d = this.params) === null || _d === void 0 ? void 0 : _d.toolConfig,
|
||
systemInstruction: (_e = this.params) === null || _e === void 0 ? void 0 : _e.systemInstruction,
|
||
cachedContent: (_f = this.params) === null || _f === void 0 ? void 0 : _f.cachedContent,
|
||
contents: [...this._history, newContent]
|
||
};
|
||
const chatSessionRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
|
||
const streamPromise = generateContentStream(this._apiKey, this.model, generateContentRequest, chatSessionRequestOptions);
|
||
this._sendPromise = this._sendPromise.then(() => streamPromise).catch((_ignored) => {
|
||
throw new Error(SILENT_ERROR);
|
||
}).then((streamResult) => streamResult.response).then((response) => {
|
||
if (response.candidates && response.candidates.length > 0) {
|
||
this._history.push(newContent);
|
||
const responseContent = Object.assign({}, response.candidates[0].content);
|
||
if (!responseContent.role) {
|
||
responseContent.role = "model";
|
||
}
|
||
this._history.push(responseContent);
|
||
} else {
|
||
const blockErrorMessage = formatBlockErrorMessage(response);
|
||
if (blockErrorMessage) {
|
||
console.warn(`sendMessageStream() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.`);
|
||
}
|
||
}
|
||
}).catch((e) => {
|
||
if (e.message !== SILENT_ERROR) {
|
||
console.error(e);
|
||
}
|
||
});
|
||
return streamPromise;
|
||
}
|
||
};
|
||
async function countTokens(apiKey, model, params, singleRequestOptions) {
|
||
const response = await makeModelRequest(model, Task.COUNT_TOKENS, apiKey, false, JSON.stringify(params), singleRequestOptions);
|
||
return response.json();
|
||
}
|
||
async function embedContent(apiKey, model, params, requestOptions) {
|
||
const response = await makeModelRequest(model, Task.EMBED_CONTENT, apiKey, false, JSON.stringify(params), requestOptions);
|
||
return response.json();
|
||
}
|
||
async function batchEmbedContents(apiKey, model, params, requestOptions) {
|
||
const requestsWithModel = params.requests.map((request) => {
|
||
return Object.assign(Object.assign({}, request), { model });
|
||
});
|
||
const response = await makeModelRequest(model, Task.BATCH_EMBED_CONTENTS, apiKey, false, JSON.stringify({ requests: requestsWithModel }), requestOptions);
|
||
return response.json();
|
||
}
|
||
var GenerativeModel = class {
|
||
constructor(apiKey, modelParams, _requestOptions = {}) {
|
||
this.apiKey = apiKey;
|
||
this._requestOptions = _requestOptions;
|
||
if (modelParams.model.includes("/")) {
|
||
this.model = modelParams.model;
|
||
} else {
|
||
this.model = `models/${modelParams.model}`;
|
||
}
|
||
this.generationConfig = modelParams.generationConfig || {};
|
||
this.safetySettings = modelParams.safetySettings || [];
|
||
this.tools = modelParams.tools;
|
||
this.toolConfig = modelParams.toolConfig;
|
||
this.systemInstruction = formatSystemInstruction(modelParams.systemInstruction);
|
||
this.cachedContent = modelParams.cachedContent;
|
||
}
|
||
/**
|
||
* Makes a single non-streaming call to the model
|
||
* and returns an object containing a single {@link GenerateContentResponse}.
|
||
*
|
||
* Fields set in the optional {@link SingleRequestOptions} parameter will
|
||
* take precedence over the {@link RequestOptions} values provided to
|
||
* {@link GoogleGenerativeAI.getGenerativeModel }.
|
||
*/
|
||
async generateContent(request, requestOptions = {}) {
|
||
var _a2;
|
||
const formattedParams = formatGenerateContentInput(request);
|
||
const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
|
||
return generateContent(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a2 = this.cachedContent) === null || _a2 === void 0 ? void 0 : _a2.name }, formattedParams), generativeModelRequestOptions);
|
||
}
|
||
/**
|
||
* Makes a single streaming call to the model and returns an object
|
||
* containing an iterable stream that iterates over all chunks in the
|
||
* streaming response as well as a promise that returns the final
|
||
* aggregated response.
|
||
*
|
||
* Fields set in the optional {@link SingleRequestOptions} parameter will
|
||
* take precedence over the {@link RequestOptions} values provided to
|
||
* {@link GoogleGenerativeAI.getGenerativeModel }.
|
||
*/
|
||
async generateContentStream(request, requestOptions = {}) {
|
||
var _a2;
|
||
const formattedParams = formatGenerateContentInput(request);
|
||
const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
|
||
return generateContentStream(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a2 = this.cachedContent) === null || _a2 === void 0 ? void 0 : _a2.name }, formattedParams), generativeModelRequestOptions);
|
||
}
|
||
/**
|
||
* Gets a new {@link ChatSession} instance which can be used for
|
||
* multi-turn chats.
|
||
*/
|
||
startChat(startChatParams) {
|
||
var _a2;
|
||
return new ChatSession(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, cachedContent: (_a2 = this.cachedContent) === null || _a2 === void 0 ? void 0 : _a2.name }, startChatParams), this._requestOptions);
|
||
}
|
||
/**
|
||
* Counts the tokens in the provided request.
|
||
*
|
||
* Fields set in the optional {@link SingleRequestOptions} parameter will
|
||
* take precedence over the {@link RequestOptions} values provided to
|
||
* {@link GoogleGenerativeAI.getGenerativeModel }.
|
||
*/
|
||
async countTokens(request, requestOptions = {}) {
|
||
const formattedParams = formatCountTokensInput(request, {
|
||
model: this.model,
|
||
generationConfig: this.generationConfig,
|
||
safetySettings: this.safetySettings,
|
||
tools: this.tools,
|
||
toolConfig: this.toolConfig,
|
||
systemInstruction: this.systemInstruction,
|
||
cachedContent: this.cachedContent
|
||
});
|
||
const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
|
||
return countTokens(this.apiKey, this.model, formattedParams, generativeModelRequestOptions);
|
||
}
|
||
/**
|
||
* Embeds the provided content.
|
||
*
|
||
* Fields set in the optional {@link SingleRequestOptions} parameter will
|
||
* take precedence over the {@link RequestOptions} values provided to
|
||
* {@link GoogleGenerativeAI.getGenerativeModel }.
|
||
*/
|
||
async embedContent(request, requestOptions = {}) {
|
||
const formattedParams = formatEmbedContentInput(request);
|
||
const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
|
||
return embedContent(this.apiKey, this.model, formattedParams, generativeModelRequestOptions);
|
||
}
|
||
/**
|
||
* Embeds an array of {@link EmbedContentRequest}s.
|
||
*
|
||
* Fields set in the optional {@link SingleRequestOptions} parameter will
|
||
* take precedence over the {@link RequestOptions} values provided to
|
||
* {@link GoogleGenerativeAI.getGenerativeModel }.
|
||
*/
|
||
async batchEmbedContents(batchEmbedContentRequest, requestOptions = {}) {
|
||
const generativeModelRequestOptions = Object.assign(Object.assign({}, this._requestOptions), requestOptions);
|
||
return batchEmbedContents(this.apiKey, this.model, batchEmbedContentRequest, generativeModelRequestOptions);
|
||
}
|
||
};
|
||
var GoogleGenerativeAI = class {
|
||
constructor(apiKey) {
|
||
this.apiKey = apiKey;
|
||
}
|
||
/**
|
||
* Gets a {@link GenerativeModel} instance for the provided model name.
|
||
*/
|
||
getGenerativeModel(modelParams, requestOptions) {
|
||
if (!modelParams.model) {
|
||
throw new GoogleGenerativeAIError(`Must provide a model name. Example: genai.getGenerativeModel({ model: 'my-model-name' })`);
|
||
}
|
||
return new GenerativeModel(this.apiKey, modelParams, requestOptions);
|
||
}
|
||
/**
|
||
* Creates a {@link GenerativeModel} instance from provided content cache.
|
||
*/
|
||
getGenerativeModelFromCachedContent(cachedContent, modelParams, requestOptions) {
|
||
if (!cachedContent.name) {
|
||
throw new GoogleGenerativeAIRequestInputError("Cached content must contain a `name` field.");
|
||
}
|
||
if (!cachedContent.model) {
|
||
throw new GoogleGenerativeAIRequestInputError("Cached content must contain a `model` field.");
|
||
}
|
||
const disallowedDuplicates = ["model", "systemInstruction"];
|
||
for (const key of disallowedDuplicates) {
|
||
if ((modelParams === null || modelParams === void 0 ? void 0 : modelParams[key]) && cachedContent[key] && (modelParams === null || modelParams === void 0 ? void 0 : modelParams[key]) !== cachedContent[key]) {
|
||
if (key === "model") {
|
||
const modelParamsComp = modelParams.model.startsWith("models/") ? modelParams.model.replace("models/", "") : modelParams.model;
|
||
const cachedContentComp = cachedContent.model.startsWith("models/") ? cachedContent.model.replace("models/", "") : cachedContent.model;
|
||
if (modelParamsComp === cachedContentComp) {
|
||
continue;
|
||
}
|
||
}
|
||
throw new GoogleGenerativeAIRequestInputError(`Different value for "${key}" specified in modelParams (${modelParams[key]}) and cachedContent (${cachedContent[key]})`);
|
||
}
|
||
}
|
||
const modelParamsFromCache = Object.assign(Object.assign({}, modelParams), { model: cachedContent.model, tools: cachedContent.tools, toolConfig: cachedContent.toolConfig, systemInstruction: cachedContent.systemInstruction, cachedContent });
|
||
return new GenerativeModel(this.apiKey, modelParamsFromCache, requestOptions);
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/internal/qs/formats.mjs
|
||
var default_format = "RFC3986";
|
||
var formatters = {
|
||
RFC1738: (v) => String(v).replace(/%20/g, "+"),
|
||
RFC3986: (v) => String(v)
|
||
};
|
||
var RFC1738 = "RFC1738";
|
||
|
||
// node_modules/openai/internal/qs/utils.mjs
|
||
var is_array = Array.isArray;
|
||
var hex_table = (() => {
|
||
const array = [];
|
||
for (let i = 0; i < 256; ++i) {
|
||
array.push("%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase());
|
||
}
|
||
return array;
|
||
})();
|
||
var limit = 1024;
|
||
var encode = (str2, _defaultEncoder, charset, _kind, format) => {
|
||
if (str2.length === 0) {
|
||
return str2;
|
||
}
|
||
let string = str2;
|
||
if (typeof str2 === "symbol") {
|
||
string = Symbol.prototype.toString.call(str2);
|
||
} else if (typeof str2 !== "string") {
|
||
string = String(str2);
|
||
}
|
||
if (charset === "iso-8859-1") {
|
||
return escape(string).replace(/%u[0-9a-f]{4}/gi, function($0) {
|
||
return "%26%23" + parseInt($0.slice(2), 16) + "%3B";
|
||
});
|
||
}
|
||
let out = "";
|
||
for (let j = 0; j < string.length; j += limit) {
|
||
const segment = string.length >= limit ? string.slice(j, j + limit) : string;
|
||
const arr = [];
|
||
for (let i = 0; i < segment.length; ++i) {
|
||
let c = segment.charCodeAt(i);
|
||
if (c === 45 || // -
|
||
c === 46 || // .
|
||
c === 95 || // _
|
||
c === 126 || // ~
|
||
c >= 48 && c <= 57 || // 0-9
|
||
c >= 65 && c <= 90 || // a-z
|
||
c >= 97 && c <= 122 || // A-Z
|
||
format === RFC1738 && (c === 40 || c === 41)) {
|
||
arr[arr.length] = segment.charAt(i);
|
||
continue;
|
||
}
|
||
if (c < 128) {
|
||
arr[arr.length] = hex_table[c];
|
||
continue;
|
||
}
|
||
if (c < 2048) {
|
||
arr[arr.length] = hex_table[192 | c >> 6] + hex_table[128 | c & 63];
|
||
continue;
|
||
}
|
||
if (c < 55296 || c >= 57344) {
|
||
arr[arr.length] = hex_table[224 | c >> 12] + hex_table[128 | c >> 6 & 63] + hex_table[128 | c & 63];
|
||
continue;
|
||
}
|
||
i += 1;
|
||
c = 65536 + ((c & 1023) << 10 | segment.charCodeAt(i) & 1023);
|
||
arr[arr.length] = hex_table[240 | c >> 18] + hex_table[128 | c >> 12 & 63] + hex_table[128 | c >> 6 & 63] + hex_table[128 | c & 63];
|
||
}
|
||
out += arr.join("");
|
||
}
|
||
return out;
|
||
};
|
||
function is_buffer(obj) {
|
||
if (!obj || typeof obj !== "object") {
|
||
return false;
|
||
}
|
||
return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
|
||
}
|
||
function maybe_map(val, fn) {
|
||
if (is_array(val)) {
|
||
const mapped = [];
|
||
for (let i = 0; i < val.length; i += 1) {
|
||
mapped.push(fn(val[i]));
|
||
}
|
||
return mapped;
|
||
}
|
||
return fn(val);
|
||
}
|
||
|
||
// node_modules/openai/internal/qs/stringify.mjs
|
||
var has = Object.prototype.hasOwnProperty;
|
||
var array_prefix_generators = {
|
||
brackets(prefix) {
|
||
return String(prefix) + "[]";
|
||
},
|
||
comma: "comma",
|
||
indices(prefix, key) {
|
||
return String(prefix) + "[" + key + "]";
|
||
},
|
||
repeat(prefix) {
|
||
return String(prefix);
|
||
}
|
||
};
|
||
var is_array2 = Array.isArray;
|
||
var push = Array.prototype.push;
|
||
var push_to_array = function(arr, value_or_array) {
|
||
push.apply(arr, is_array2(value_or_array) ? value_or_array : [value_or_array]);
|
||
};
|
||
var to_ISO = Date.prototype.toISOString;
|
||
var defaults = {
|
||
addQueryPrefix: false,
|
||
allowDots: false,
|
||
allowEmptyArrays: false,
|
||
arrayFormat: "indices",
|
||
charset: "utf-8",
|
||
charsetSentinel: false,
|
||
delimiter: "&",
|
||
encode: true,
|
||
encodeDotInKeys: false,
|
||
encoder: encode,
|
||
encodeValuesOnly: false,
|
||
format: default_format,
|
||
formatter: formatters[default_format],
|
||
/** @deprecated */
|
||
indices: false,
|
||
serializeDate(date) {
|
||
return to_ISO.call(date);
|
||
},
|
||
skipNulls: false,
|
||
strictNullHandling: false
|
||
};
|
||
function is_non_nullish_primitive(v) {
|
||
return typeof v === "string" || typeof v === "number" || typeof v === "boolean" || typeof v === "symbol" || typeof v === "bigint";
|
||
}
|
||
var sentinel = {};
|
||
function inner_stringify(object, prefix, generateArrayPrefix, commaRoundTrip, allowEmptyArrays, strictNullHandling, skipNulls, encodeDotInKeys, encoder, filter, sort, allowDots, serializeDate, format, formatter, encodeValuesOnly, charset, sideChannel) {
|
||
let obj = object;
|
||
let tmp_sc = sideChannel;
|
||
let step = 0;
|
||
let find_flag = false;
|
||
while ((tmp_sc = tmp_sc.get(sentinel)) !== void 0 && !find_flag) {
|
||
const pos = tmp_sc.get(object);
|
||
step += 1;
|
||
if (typeof pos !== "undefined") {
|
||
if (pos === step) {
|
||
throw new RangeError("Cyclic object value");
|
||
} else {
|
||
find_flag = true;
|
||
}
|
||
}
|
||
if (typeof tmp_sc.get(sentinel) === "undefined") {
|
||
step = 0;
|
||
}
|
||
}
|
||
if (typeof filter === "function") {
|
||
obj = filter(prefix, obj);
|
||
} else if (obj instanceof Date) {
|
||
obj = serializeDate == null ? void 0 : serializeDate(obj);
|
||
} else if (generateArrayPrefix === "comma" && is_array2(obj)) {
|
||
obj = maybe_map(obj, function(value) {
|
||
if (value instanceof Date) {
|
||
return serializeDate == null ? void 0 : serializeDate(value);
|
||
}
|
||
return value;
|
||
});
|
||
}
|
||
if (obj === null) {
|
||
if (strictNullHandling) {
|
||
return encoder && !encodeValuesOnly ? (
|
||
// @ts-expect-error
|
||
encoder(prefix, defaults.encoder, charset, "key", format)
|
||
) : prefix;
|
||
}
|
||
obj = "";
|
||
}
|
||
if (is_non_nullish_primitive(obj) || is_buffer(obj)) {
|
||
if (encoder) {
|
||
const key_value = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, "key", format);
|
||
return [
|
||
(formatter == null ? void 0 : formatter(key_value)) + "=" + // @ts-expect-error
|
||
(formatter == null ? void 0 : formatter(encoder(obj, defaults.encoder, charset, "value", format)))
|
||
];
|
||
}
|
||
return [(formatter == null ? void 0 : formatter(prefix)) + "=" + (formatter == null ? void 0 : formatter(String(obj)))];
|
||
}
|
||
const values = [];
|
||
if (typeof obj === "undefined") {
|
||
return values;
|
||
}
|
||
let obj_keys;
|
||
if (generateArrayPrefix === "comma" && is_array2(obj)) {
|
||
if (encodeValuesOnly && encoder) {
|
||
obj = maybe_map(obj, encoder);
|
||
}
|
||
obj_keys = [{ value: obj.length > 0 ? obj.join(",") || null : void 0 }];
|
||
} else if (is_array2(filter)) {
|
||
obj_keys = filter;
|
||
} else {
|
||
const keys = Object.keys(obj);
|
||
obj_keys = sort ? keys.sort(sort) : keys;
|
||
}
|
||
const encoded_prefix = encodeDotInKeys ? String(prefix).replace(/\./g, "%2E") : String(prefix);
|
||
const adjusted_prefix = commaRoundTrip && is_array2(obj) && obj.length === 1 ? encoded_prefix + "[]" : encoded_prefix;
|
||
if (allowEmptyArrays && is_array2(obj) && obj.length === 0) {
|
||
return adjusted_prefix + "[]";
|
||
}
|
||
for (let j = 0; j < obj_keys.length; ++j) {
|
||
const key = obj_keys[j];
|
||
const value = (
|
||
// @ts-ignore
|
||
typeof key === "object" && typeof key.value !== "undefined" ? key.value : obj[key]
|
||
);
|
||
if (skipNulls && value === null) {
|
||
continue;
|
||
}
|
||
const encoded_key = allowDots && encodeDotInKeys ? key.replace(/\./g, "%2E") : key;
|
||
const key_prefix = is_array2(obj) ? typeof generateArrayPrefix === "function" ? generateArrayPrefix(adjusted_prefix, encoded_key) : adjusted_prefix : adjusted_prefix + (allowDots ? "." + encoded_key : "[" + encoded_key + "]");
|
||
sideChannel.set(object, step);
|
||
const valueSideChannel = /* @__PURE__ */ new WeakMap();
|
||
valueSideChannel.set(sentinel, sideChannel);
|
||
push_to_array(values, inner_stringify(
|
||
value,
|
||
key_prefix,
|
||
generateArrayPrefix,
|
||
commaRoundTrip,
|
||
allowEmptyArrays,
|
||
strictNullHandling,
|
||
skipNulls,
|
||
encodeDotInKeys,
|
||
// @ts-ignore
|
||
generateArrayPrefix === "comma" && encodeValuesOnly && is_array2(obj) ? null : encoder,
|
||
filter,
|
||
sort,
|
||
allowDots,
|
||
serializeDate,
|
||
format,
|
||
formatter,
|
||
encodeValuesOnly,
|
||
charset,
|
||
valueSideChannel
|
||
));
|
||
}
|
||
return values;
|
||
}
|
||
function normalize_stringify_options(opts = defaults) {
|
||
if (typeof opts.allowEmptyArrays !== "undefined" && typeof opts.allowEmptyArrays !== "boolean") {
|
||
throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");
|
||
}
|
||
if (typeof opts.encodeDotInKeys !== "undefined" && typeof opts.encodeDotInKeys !== "boolean") {
|
||
throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided");
|
||
}
|
||
if (opts.encoder !== null && typeof opts.encoder !== "undefined" && typeof opts.encoder !== "function") {
|
||
throw new TypeError("Encoder has to be a function.");
|
||
}
|
||
const charset = opts.charset || defaults.charset;
|
||
if (typeof opts.charset !== "undefined" && opts.charset !== "utf-8" && opts.charset !== "iso-8859-1") {
|
||
throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");
|
||
}
|
||
let format = default_format;
|
||
if (typeof opts.format !== "undefined") {
|
||
if (!has.call(formatters, opts.format)) {
|
||
throw new TypeError("Unknown format option provided.");
|
||
}
|
||
format = opts.format;
|
||
}
|
||
const formatter = formatters[format];
|
||
let filter = defaults.filter;
|
||
if (typeof opts.filter === "function" || is_array2(opts.filter)) {
|
||
filter = opts.filter;
|
||
}
|
||
let arrayFormat;
|
||
if (opts.arrayFormat && opts.arrayFormat in array_prefix_generators) {
|
||
arrayFormat = opts.arrayFormat;
|
||
} else if ("indices" in opts) {
|
||
arrayFormat = opts.indices ? "indices" : "repeat";
|
||
} else {
|
||
arrayFormat = defaults.arrayFormat;
|
||
}
|
||
if ("commaRoundTrip" in opts && typeof opts.commaRoundTrip !== "boolean") {
|
||
throw new TypeError("`commaRoundTrip` must be a boolean, or absent");
|
||
}
|
||
const allowDots = typeof opts.allowDots === "undefined" ? !!opts.encodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;
|
||
return {
|
||
addQueryPrefix: typeof opts.addQueryPrefix === "boolean" ? opts.addQueryPrefix : defaults.addQueryPrefix,
|
||
// @ts-ignore
|
||
allowDots,
|
||
allowEmptyArrays: typeof opts.allowEmptyArrays === "boolean" ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
|
||
arrayFormat,
|
||
charset,
|
||
charsetSentinel: typeof opts.charsetSentinel === "boolean" ? opts.charsetSentinel : defaults.charsetSentinel,
|
||
commaRoundTrip: !!opts.commaRoundTrip,
|
||
delimiter: typeof opts.delimiter === "undefined" ? defaults.delimiter : opts.delimiter,
|
||
encode: typeof opts.encode === "boolean" ? opts.encode : defaults.encode,
|
||
encodeDotInKeys: typeof opts.encodeDotInKeys === "boolean" ? opts.encodeDotInKeys : defaults.encodeDotInKeys,
|
||
encoder: typeof opts.encoder === "function" ? opts.encoder : defaults.encoder,
|
||
encodeValuesOnly: typeof opts.encodeValuesOnly === "boolean" ? opts.encodeValuesOnly : defaults.encodeValuesOnly,
|
||
filter,
|
||
format,
|
||
formatter,
|
||
serializeDate: typeof opts.serializeDate === "function" ? opts.serializeDate : defaults.serializeDate,
|
||
skipNulls: typeof opts.skipNulls === "boolean" ? opts.skipNulls : defaults.skipNulls,
|
||
// @ts-ignore
|
||
sort: typeof opts.sort === "function" ? opts.sort : null,
|
||
strictNullHandling: typeof opts.strictNullHandling === "boolean" ? opts.strictNullHandling : defaults.strictNullHandling
|
||
};
|
||
}
|
||
function stringify(object, opts = {}) {
|
||
let obj = object;
|
||
const options = normalize_stringify_options(opts);
|
||
let obj_keys;
|
||
let filter;
|
||
if (typeof options.filter === "function") {
|
||
filter = options.filter;
|
||
obj = filter("", obj);
|
||
} else if (is_array2(options.filter)) {
|
||
filter = options.filter;
|
||
obj_keys = filter;
|
||
}
|
||
const keys = [];
|
||
if (typeof obj !== "object" || obj === null) {
|
||
return "";
|
||
}
|
||
const generateArrayPrefix = array_prefix_generators[options.arrayFormat];
|
||
const commaRoundTrip = generateArrayPrefix === "comma" && options.commaRoundTrip;
|
||
if (!obj_keys) {
|
||
obj_keys = Object.keys(obj);
|
||
}
|
||
if (options.sort) {
|
||
obj_keys.sort(options.sort);
|
||
}
|
||
const sideChannel = /* @__PURE__ */ new WeakMap();
|
||
for (let i = 0; i < obj_keys.length; ++i) {
|
||
const key = obj_keys[i];
|
||
if (options.skipNulls && obj[key] === null) {
|
||
continue;
|
||
}
|
||
push_to_array(keys, inner_stringify(
|
||
obj[key],
|
||
key,
|
||
// @ts-expect-error
|
||
generateArrayPrefix,
|
||
commaRoundTrip,
|
||
options.allowEmptyArrays,
|
||
options.strictNullHandling,
|
||
options.skipNulls,
|
||
options.encodeDotInKeys,
|
||
options.encode ? options.encoder : null,
|
||
options.filter,
|
||
options.sort,
|
||
options.allowDots,
|
||
options.serializeDate,
|
||
options.format,
|
||
options.formatter,
|
||
options.encodeValuesOnly,
|
||
options.charset,
|
||
sideChannel
|
||
));
|
||
}
|
||
const joined = keys.join(options.delimiter);
|
||
let prefix = options.addQueryPrefix === true ? "?" : "";
|
||
if (options.charsetSentinel) {
|
||
if (options.charset === "iso-8859-1") {
|
||
prefix += "utf8=%26%2310003%3B&";
|
||
} else {
|
||
prefix += "utf8=%E2%9C%93&";
|
||
}
|
||
}
|
||
return joined.length > 0 ? prefix + joined : "";
|
||
}
|
||
|
||
// node_modules/openai/version.mjs
|
||
var VERSION = "4.76.1";
|
||
|
||
// node_modules/openai/_shims/registry.mjs
|
||
var auto = false;
|
||
var kind = void 0;
|
||
var fetch2 = void 0;
|
||
var Request2 = void 0;
|
||
var Response2 = void 0;
|
||
var Headers2 = void 0;
|
||
var FormData2 = void 0;
|
||
var Blob2 = void 0;
|
||
var File2 = void 0;
|
||
var ReadableStream2 = void 0;
|
||
var getMultipartRequestOptions = void 0;
|
||
var getDefaultAgent = void 0;
|
||
var fileFromPath = void 0;
|
||
var isFsReadStream = void 0;
|
||
function setShims(shims, options = { auto: false }) {
|
||
if (auto) {
|
||
throw new Error(`you must \`import 'openai/shims/${shims.kind}'\` before importing anything else from openai`);
|
||
}
|
||
if (kind) {
|
||
throw new Error(`can't \`import 'openai/shims/${shims.kind}'\` after \`import 'openai/shims/${kind}'\``);
|
||
}
|
||
auto = options.auto;
|
||
kind = shims.kind;
|
||
fetch2 = shims.fetch;
|
||
Request2 = shims.Request;
|
||
Response2 = shims.Response;
|
||
Headers2 = shims.Headers;
|
||
FormData2 = shims.FormData;
|
||
Blob2 = shims.Blob;
|
||
File2 = shims.File;
|
||
ReadableStream2 = shims.ReadableStream;
|
||
getMultipartRequestOptions = shims.getMultipartRequestOptions;
|
||
getDefaultAgent = shims.getDefaultAgent;
|
||
fileFromPath = shims.fileFromPath;
|
||
isFsReadStream = shims.isFsReadStream;
|
||
}
|
||
|
||
// node_modules/openai/_shims/MultipartBody.mjs
|
||
var MultipartBody = class {
|
||
constructor(body) {
|
||
this.body = body;
|
||
}
|
||
get [Symbol.toStringTag]() {
|
||
return "MultipartBody";
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/_shims/web-runtime.mjs
|
||
function getRuntime({ manuallyImported } = {}) {
|
||
const recommendation = manuallyImported ? `You may need to use polyfills` : `Add one of these imports before your first \`import \u2026 from 'openai'\`:
|
||
- \`import 'openai/shims/node'\` (if you're running on Node)
|
||
- \`import 'openai/shims/web'\` (otherwise)
|
||
`;
|
||
let _fetch, _Request, _Response, _Headers;
|
||
try {
|
||
_fetch = fetch;
|
||
_Request = Request;
|
||
_Response = Response;
|
||
_Headers = Headers;
|
||
} catch (error) {
|
||
throw new Error(`this environment is missing the following Web Fetch API type: ${error.message}. ${recommendation}`);
|
||
}
|
||
return {
|
||
kind: "web",
|
||
fetch: _fetch,
|
||
Request: _Request,
|
||
Response: _Response,
|
||
Headers: _Headers,
|
||
FormData: (
|
||
// @ts-ignore
|
||
typeof FormData !== "undefined" ? FormData : class FormData {
|
||
// @ts-ignore
|
||
constructor() {
|
||
throw new Error(`file uploads aren't supported in this environment yet as 'FormData' is undefined. ${recommendation}`);
|
||
}
|
||
}
|
||
),
|
||
Blob: typeof Blob !== "undefined" ? Blob : class Blob {
|
||
constructor() {
|
||
throw new Error(`file uploads aren't supported in this environment yet as 'Blob' is undefined. ${recommendation}`);
|
||
}
|
||
},
|
||
File: (
|
||
// @ts-ignore
|
||
typeof File !== "undefined" ? File : class File {
|
||
// @ts-ignore
|
||
constructor() {
|
||
throw new Error(`file uploads aren't supported in this environment yet as 'File' is undefined. ${recommendation}`);
|
||
}
|
||
}
|
||
),
|
||
ReadableStream: (
|
||
// @ts-ignore
|
||
typeof ReadableStream !== "undefined" ? ReadableStream : class ReadableStream {
|
||
// @ts-ignore
|
||
constructor() {
|
||
throw new Error(`streaming isn't supported in this environment yet as 'ReadableStream' is undefined. ${recommendation}`);
|
||
}
|
||
}
|
||
),
|
||
getMultipartRequestOptions: async (form, opts) => ({
|
||
...opts,
|
||
body: new MultipartBody(form)
|
||
}),
|
||
getDefaultAgent: (url) => void 0,
|
||
fileFromPath: () => {
|
||
throw new Error("The `fileFromPath` function is only supported in Node. See the README for more details: https://www.github.com/openai/openai-node#file-uploads");
|
||
},
|
||
isFsReadStream: (value) => false
|
||
};
|
||
}
|
||
|
||
// node_modules/openai/_shims/index.mjs
|
||
if (!kind)
|
||
setShims(getRuntime(), { auto: true });
|
||
|
||
// node_modules/openai/error.mjs
|
||
var OpenAIError = class extends Error {
|
||
};
|
||
var APIError = class _APIError extends OpenAIError {
|
||
constructor(status, error, message, headers) {
|
||
super(`${_APIError.makeMessage(status, error, message)}`);
|
||
this.status = status;
|
||
this.headers = headers;
|
||
this.request_id = headers == null ? void 0 : headers["x-request-id"];
|
||
const data = error;
|
||
this.error = data;
|
||
this.code = data == null ? void 0 : data["code"];
|
||
this.param = data == null ? void 0 : data["param"];
|
||
this.type = data == null ? void 0 : data["type"];
|
||
}
|
||
static makeMessage(status, error, message) {
|
||
const msg = (error == null ? void 0 : error.message) ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : message;
|
||
if (status && msg) {
|
||
return `${status} ${msg}`;
|
||
}
|
||
if (status) {
|
||
return `${status} status code (no body)`;
|
||
}
|
||
if (msg) {
|
||
return msg;
|
||
}
|
||
return "(no status code or body)";
|
||
}
|
||
static generate(status, errorResponse, message, headers) {
|
||
if (!status) {
|
||
return new APIConnectionError({ message, cause: castToError(errorResponse) });
|
||
}
|
||
const error = errorResponse == null ? void 0 : errorResponse["error"];
|
||
if (status === 400) {
|
||
return new BadRequestError(status, error, message, headers);
|
||
}
|
||
if (status === 401) {
|
||
return new AuthenticationError(status, error, message, headers);
|
||
}
|
||
if (status === 403) {
|
||
return new PermissionDeniedError(status, error, message, headers);
|
||
}
|
||
if (status === 404) {
|
||
return new NotFoundError(status, error, message, headers);
|
||
}
|
||
if (status === 409) {
|
||
return new ConflictError(status, error, message, headers);
|
||
}
|
||
if (status === 422) {
|
||
return new UnprocessableEntityError(status, error, message, headers);
|
||
}
|
||
if (status === 429) {
|
||
return new RateLimitError(status, error, message, headers);
|
||
}
|
||
if (status >= 500) {
|
||
return new InternalServerError(status, error, message, headers);
|
||
}
|
||
return new _APIError(status, error, message, headers);
|
||
}
|
||
};
|
||
var APIUserAbortError = class extends APIError {
|
||
constructor({ message } = {}) {
|
||
super(void 0, void 0, message || "Request was aborted.", void 0);
|
||
this.status = void 0;
|
||
}
|
||
};
|
||
var APIConnectionError = class extends APIError {
|
||
constructor({ message, cause }) {
|
||
super(void 0, void 0, message || "Connection error.", void 0);
|
||
this.status = void 0;
|
||
if (cause)
|
||
this.cause = cause;
|
||
}
|
||
};
|
||
var APIConnectionTimeoutError = class extends APIConnectionError {
|
||
constructor({ message } = {}) {
|
||
super({ message: message != null ? message : "Request timed out." });
|
||
}
|
||
};
|
||
var BadRequestError = class extends APIError {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.status = 400;
|
||
}
|
||
};
|
||
var AuthenticationError = class extends APIError {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.status = 401;
|
||
}
|
||
};
|
||
var PermissionDeniedError = class extends APIError {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.status = 403;
|
||
}
|
||
};
|
||
var NotFoundError = class extends APIError {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.status = 404;
|
||
}
|
||
};
|
||
var ConflictError = class extends APIError {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.status = 409;
|
||
}
|
||
};
|
||
var UnprocessableEntityError = class extends APIError {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.status = 422;
|
||
}
|
||
};
|
||
var RateLimitError = class extends APIError {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.status = 429;
|
||
}
|
||
};
|
||
var InternalServerError = class extends APIError {
|
||
};
|
||
var LengthFinishReasonError = class extends OpenAIError {
|
||
constructor() {
|
||
super(`Could not parse response content as the length limit was reached`);
|
||
}
|
||
};
|
||
var ContentFilterFinishReasonError = class extends OpenAIError {
|
||
constructor() {
|
||
super(`Could not parse response content as the request was rejected by the content filter`);
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/internal/decoders/line.mjs
|
||
var LineDecoder = class _LineDecoder {
|
||
constructor() {
|
||
this.buffer = [];
|
||
this.trailingCR = false;
|
||
}
|
||
decode(chunk) {
|
||
let text = this.decodeText(chunk);
|
||
if (this.trailingCR) {
|
||
text = "\r" + text;
|
||
this.trailingCR = false;
|
||
}
|
||
if (text.endsWith("\r")) {
|
||
this.trailingCR = true;
|
||
text = text.slice(0, -1);
|
||
}
|
||
if (!text) {
|
||
return [];
|
||
}
|
||
const trailingNewline = _LineDecoder.NEWLINE_CHARS.has(text[text.length - 1] || "");
|
||
let lines = text.split(_LineDecoder.NEWLINE_REGEXP);
|
||
if (trailingNewline) {
|
||
lines.pop();
|
||
}
|
||
if (lines.length === 1 && !trailingNewline) {
|
||
this.buffer.push(lines[0]);
|
||
return [];
|
||
}
|
||
if (this.buffer.length > 0) {
|
||
lines = [this.buffer.join("") + lines[0], ...lines.slice(1)];
|
||
this.buffer = [];
|
||
}
|
||
if (!trailingNewline) {
|
||
this.buffer = [lines.pop() || ""];
|
||
}
|
||
return lines;
|
||
}
|
||
decodeText(bytes) {
|
||
var _a2;
|
||
if (bytes == null)
|
||
return "";
|
||
if (typeof bytes === "string")
|
||
return bytes;
|
||
if (typeof Buffer !== "undefined") {
|
||
if (bytes instanceof Buffer) {
|
||
return bytes.toString();
|
||
}
|
||
if (bytes instanceof Uint8Array) {
|
||
return Buffer.from(bytes).toString();
|
||
}
|
||
throw new OpenAIError(`Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global "Buffer" defined, which this library assumes to be Node. Please report this error.`);
|
||
}
|
||
if (typeof TextDecoder !== "undefined") {
|
||
if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) {
|
||
(_a2 = this.textDecoder) != null ? _a2 : this.textDecoder = new TextDecoder("utf8");
|
||
return this.textDecoder.decode(bytes);
|
||
}
|
||
throw new OpenAIError(`Unexpected: received non-Uint8Array/ArrayBuffer (${bytes.constructor.name}) in a web platform. Please report this error.`);
|
||
}
|
||
throw new OpenAIError(`Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.`);
|
||
}
|
||
flush() {
|
||
if (!this.buffer.length && !this.trailingCR) {
|
||
return [];
|
||
}
|
||
const lines = [this.buffer.join("")];
|
||
this.buffer = [];
|
||
this.trailingCR = false;
|
||
return lines;
|
||
}
|
||
};
|
||
LineDecoder.NEWLINE_CHARS = /* @__PURE__ */ new Set(["\n", "\r"]);
|
||
LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g;
|
||
|
||
// node_modules/openai/streaming.mjs
|
||
var Stream = class _Stream {
|
||
constructor(iterator, controller) {
|
||
this.iterator = iterator;
|
||
this.controller = controller;
|
||
}
|
||
static fromSSEResponse(response, controller) {
|
||
let consumed = false;
|
||
async function* iterator() {
|
||
if (consumed) {
|
||
throw new Error("Cannot iterate over a consumed stream, use `.tee()` to split the stream.");
|
||
}
|
||
consumed = true;
|
||
let done = false;
|
||
try {
|
||
for await (const sse of _iterSSEMessages(response, controller)) {
|
||
if (done)
|
||
continue;
|
||
if (sse.data.startsWith("[DONE]")) {
|
||
done = true;
|
||
continue;
|
||
}
|
||
if (sse.event === null) {
|
||
let data;
|
||
try {
|
||
data = JSON.parse(sse.data);
|
||
} catch (e) {
|
||
console.error(`Could not parse message into JSON:`, sse.data);
|
||
console.error(`From chunk:`, sse.raw);
|
||
throw e;
|
||
}
|
||
if (data && data.error) {
|
||
throw new APIError(void 0, data.error, void 0, void 0);
|
||
}
|
||
yield data;
|
||
} else {
|
||
let data;
|
||
try {
|
||
data = JSON.parse(sse.data);
|
||
} catch (e) {
|
||
console.error(`Could not parse message into JSON:`, sse.data);
|
||
console.error(`From chunk:`, sse.raw);
|
||
throw e;
|
||
}
|
||
if (sse.event == "error") {
|
||
throw new APIError(void 0, data.error, data.message, void 0);
|
||
}
|
||
yield { event: sse.event, data };
|
||
}
|
||
}
|
||
done = true;
|
||
} catch (e) {
|
||
if (e instanceof Error && e.name === "AbortError")
|
||
return;
|
||
throw e;
|
||
} finally {
|
||
if (!done)
|
||
controller.abort();
|
||
}
|
||
}
|
||
return new _Stream(iterator, controller);
|
||
}
|
||
/**
|
||
* Generates a Stream from a newline-separated ReadableStream
|
||
* where each item is a JSON value.
|
||
*/
|
||
static fromReadableStream(readableStream, controller) {
|
||
let consumed = false;
|
||
async function* iterLines() {
|
||
const lineDecoder = new LineDecoder();
|
||
const iter = readableStreamAsyncIterable(readableStream);
|
||
for await (const chunk of iter) {
|
||
for (const line of lineDecoder.decode(chunk)) {
|
||
yield line;
|
||
}
|
||
}
|
||
for (const line of lineDecoder.flush()) {
|
||
yield line;
|
||
}
|
||
}
|
||
async function* iterator() {
|
||
if (consumed) {
|
||
throw new Error("Cannot iterate over a consumed stream, use `.tee()` to split the stream.");
|
||
}
|
||
consumed = true;
|
||
let done = false;
|
||
try {
|
||
for await (const line of iterLines()) {
|
||
if (done)
|
||
continue;
|
||
if (line)
|
||
yield JSON.parse(line);
|
||
}
|
||
done = true;
|
||
} catch (e) {
|
||
if (e instanceof Error && e.name === "AbortError")
|
||
return;
|
||
throw e;
|
||
} finally {
|
||
if (!done)
|
||
controller.abort();
|
||
}
|
||
}
|
||
return new _Stream(iterator, controller);
|
||
}
|
||
[Symbol.asyncIterator]() {
|
||
return this.iterator();
|
||
}
|
||
/**
|
||
* Splits the stream into two streams which can be
|
||
* independently read from at different speeds.
|
||
*/
|
||
tee() {
|
||
const left = [];
|
||
const right = [];
|
||
const iterator = this.iterator();
|
||
const teeIterator = (queue) => {
|
||
return {
|
||
next: () => {
|
||
if (queue.length === 0) {
|
||
const result = iterator.next();
|
||
left.push(result);
|
||
right.push(result);
|
||
}
|
||
return queue.shift();
|
||
}
|
||
};
|
||
};
|
||
return [
|
||
new _Stream(() => teeIterator(left), this.controller),
|
||
new _Stream(() => teeIterator(right), this.controller)
|
||
];
|
||
}
|
||
/**
|
||
* Converts this stream to a newline-separated ReadableStream of
|
||
* JSON stringified values in the stream
|
||
* which can be turned back into a Stream with `Stream.fromReadableStream()`.
|
||
*/
|
||
toReadableStream() {
|
||
const self = this;
|
||
let iter;
|
||
const encoder = new TextEncoder();
|
||
return new ReadableStream2({
|
||
async start() {
|
||
iter = self[Symbol.asyncIterator]();
|
||
},
|
||
async pull(ctrl) {
|
||
try {
|
||
const { value, done } = await iter.next();
|
||
if (done)
|
||
return ctrl.close();
|
||
const bytes = encoder.encode(JSON.stringify(value) + "\n");
|
||
ctrl.enqueue(bytes);
|
||
} catch (err) {
|
||
ctrl.error(err);
|
||
}
|
||
},
|
||
async cancel() {
|
||
var _a2;
|
||
await ((_a2 = iter.return) == null ? void 0 : _a2.call(iter));
|
||
}
|
||
});
|
||
}
|
||
};
|
||
async function* _iterSSEMessages(response, controller) {
|
||
if (!response.body) {
|
||
controller.abort();
|
||
throw new OpenAIError(`Attempted to iterate over a response with no body`);
|
||
}
|
||
const sseDecoder = new SSEDecoder();
|
||
const lineDecoder = new LineDecoder();
|
||
const iter = readableStreamAsyncIterable(response.body);
|
||
for await (const sseChunk of iterSSEChunks(iter)) {
|
||
for (const line of lineDecoder.decode(sseChunk)) {
|
||
const sse = sseDecoder.decode(line);
|
||
if (sse)
|
||
yield sse;
|
||
}
|
||
}
|
||
for (const line of lineDecoder.flush()) {
|
||
const sse = sseDecoder.decode(line);
|
||
if (sse)
|
||
yield sse;
|
||
}
|
||
}
|
||
async function* iterSSEChunks(iterator) {
|
||
let data = new Uint8Array();
|
||
for await (const chunk of iterator) {
|
||
if (chunk == null) {
|
||
continue;
|
||
}
|
||
const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) : typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk;
|
||
let newData = new Uint8Array(data.length + binaryChunk.length);
|
||
newData.set(data);
|
||
newData.set(binaryChunk, data.length);
|
||
data = newData;
|
||
let patternIndex;
|
||
while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) {
|
||
yield data.slice(0, patternIndex);
|
||
data = data.slice(patternIndex);
|
||
}
|
||
}
|
||
if (data.length > 0) {
|
||
yield data;
|
||
}
|
||
}
|
||
function findDoubleNewlineIndex(buffer) {
|
||
const newline = 10;
|
||
const carriage = 13;
|
||
for (let i = 0; i < buffer.length - 2; i++) {
|
||
if (buffer[i] === newline && buffer[i + 1] === newline) {
|
||
return i + 2;
|
||
}
|
||
if (buffer[i] === carriage && buffer[i + 1] === carriage) {
|
||
return i + 2;
|
||
}
|
||
if (buffer[i] === carriage && buffer[i + 1] === newline && i + 3 < buffer.length && buffer[i + 2] === carriage && buffer[i + 3] === newline) {
|
||
return i + 4;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
var SSEDecoder = class {
|
||
constructor() {
|
||
this.event = null;
|
||
this.data = [];
|
||
this.chunks = [];
|
||
}
|
||
decode(line) {
|
||
if (line.endsWith("\r")) {
|
||
line = line.substring(0, line.length - 1);
|
||
}
|
||
if (!line) {
|
||
if (!this.event && !this.data.length)
|
||
return null;
|
||
const sse = {
|
||
event: this.event,
|
||
data: this.data.join("\n"),
|
||
raw: this.chunks
|
||
};
|
||
this.event = null;
|
||
this.data = [];
|
||
this.chunks = [];
|
||
return sse;
|
||
}
|
||
this.chunks.push(line);
|
||
if (line.startsWith(":")) {
|
||
return null;
|
||
}
|
||
let [fieldname, _, value] = partition(line, ":");
|
||
if (value.startsWith(" ")) {
|
||
value = value.substring(1);
|
||
}
|
||
if (fieldname === "event") {
|
||
this.event = value;
|
||
} else if (fieldname === "data") {
|
||
this.data.push(value);
|
||
}
|
||
return null;
|
||
}
|
||
};
|
||
function partition(str2, delimiter) {
|
||
const index = str2.indexOf(delimiter);
|
||
if (index !== -1) {
|
||
return [str2.substring(0, index), delimiter, str2.substring(index + delimiter.length)];
|
||
}
|
||
return [str2, "", ""];
|
||
}
|
||
function readableStreamAsyncIterable(stream) {
|
||
if (stream[Symbol.asyncIterator])
|
||
return stream;
|
||
const reader = stream.getReader();
|
||
return {
|
||
async next() {
|
||
try {
|
||
const result = await reader.read();
|
||
if (result == null ? void 0 : result.done)
|
||
reader.releaseLock();
|
||
return result;
|
||
} catch (e) {
|
||
reader.releaseLock();
|
||
throw e;
|
||
}
|
||
},
|
||
async return() {
|
||
const cancelPromise = reader.cancel();
|
||
reader.releaseLock();
|
||
await cancelPromise;
|
||
return { done: true, value: void 0 };
|
||
},
|
||
[Symbol.asyncIterator]() {
|
||
return this;
|
||
}
|
||
};
|
||
}
|
||
|
||
// node_modules/openai/uploads.mjs
|
||
var isResponseLike = (value) => value != null && typeof value === "object" && typeof value.url === "string" && typeof value.blob === "function";
|
||
var isFileLike = (value) => value != null && typeof value === "object" && typeof value.name === "string" && typeof value.lastModified === "number" && isBlobLike(value);
|
||
var isBlobLike = (value) => value != null && typeof value === "object" && typeof value.size === "number" && typeof value.type === "string" && typeof value.text === "function" && typeof value.slice === "function" && typeof value.arrayBuffer === "function";
|
||
var isUploadable = (value) => {
|
||
return isFileLike(value) || isResponseLike(value) || isFsReadStream(value);
|
||
};
|
||
async function toFile(value, name, options) {
|
||
var _a2, _b, _c;
|
||
value = await value;
|
||
if (isFileLike(value)) {
|
||
return value;
|
||
}
|
||
if (isResponseLike(value)) {
|
||
const blob = await value.blob();
|
||
name || (name = (_a2 = new URL(value.url).pathname.split(/[\\/]/).pop()) != null ? _a2 : "unknown_file");
|
||
const data = isBlobLike(blob) ? [await blob.arrayBuffer()] : [blob];
|
||
return new File2(data, name, options);
|
||
}
|
||
const bits = await getBytes(value);
|
||
name || (name = (_b = getName(value)) != null ? _b : "unknown_file");
|
||
if (!(options == null ? void 0 : options.type)) {
|
||
const type = (_c = bits[0]) == null ? void 0 : _c.type;
|
||
if (typeof type === "string") {
|
||
options = { ...options, type };
|
||
}
|
||
}
|
||
return new File2(bits, name, options);
|
||
}
|
||
async function getBytes(value) {
|
||
var _a2;
|
||
let parts = [];
|
||
if (typeof value === "string" || ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.
|
||
value instanceof ArrayBuffer) {
|
||
parts.push(value);
|
||
} else if (isBlobLike(value)) {
|
||
parts.push(await value.arrayBuffer());
|
||
} else if (isAsyncIterableIterator(value)) {
|
||
for await (const chunk of value) {
|
||
parts.push(chunk);
|
||
}
|
||
} else {
|
||
throw new Error(`Unexpected data type: ${typeof value}; constructor: ${(_a2 = value == null ? void 0 : value.constructor) == null ? void 0 : _a2.name}; props: ${propsForError(value)}`);
|
||
}
|
||
return parts;
|
||
}
|
||
function propsForError(value) {
|
||
const props = Object.getOwnPropertyNames(value);
|
||
return `[${props.map((p) => `"${p}"`).join(", ")}]`;
|
||
}
|
||
function getName(value) {
|
||
var _a2;
|
||
return getStringFromMaybeBuffer(value.name) || getStringFromMaybeBuffer(value.filename) || // For fs.ReadStream
|
||
((_a2 = getStringFromMaybeBuffer(value.path)) == null ? void 0 : _a2.split(/[\\/]/).pop());
|
||
}
|
||
var getStringFromMaybeBuffer = (x) => {
|
||
if (typeof x === "string")
|
||
return x;
|
||
if (typeof Buffer !== "undefined" && x instanceof Buffer)
|
||
return String(x);
|
||
return void 0;
|
||
};
|
||
var isAsyncIterableIterator = (value) => value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
||
var isMultipartBody = (body) => body && typeof body === "object" && body.body && body[Symbol.toStringTag] === "MultipartBody";
|
||
var multipartFormRequestOptions = async (opts) => {
|
||
const form = await createForm(opts.body);
|
||
return getMultipartRequestOptions(form, opts);
|
||
};
|
||
var createForm = async (body) => {
|
||
const form = new FormData2();
|
||
await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value)));
|
||
return form;
|
||
};
|
||
var addFormValue = async (form, key, value) => {
|
||
if (value === void 0)
|
||
return;
|
||
if (value == null) {
|
||
throw new TypeError(`Received null for "${key}"; to pass null in FormData, you must use the string 'null'`);
|
||
}
|
||
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
||
form.append(key, String(value));
|
||
} else if (isUploadable(value)) {
|
||
const file = await toFile(value);
|
||
form.append(key, file);
|
||
} else if (Array.isArray(value)) {
|
||
await Promise.all(value.map((entry) => addFormValue(form, key + "[]", entry)));
|
||
} else if (typeof value === "object") {
|
||
await Promise.all(Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)));
|
||
} else {
|
||
throw new TypeError(`Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`);
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/core.mjs
|
||
var __classPrivateFieldSet = function(receiver, state, value, kind2, f) {
|
||
if (kind2 === "m")
|
||
throw new TypeError("Private method is not writable");
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a setter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
||
return kind2 === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
|
||
};
|
||
var __classPrivateFieldGet = function(receiver, state, kind2, f) {
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a getter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||
return kind2 === "m" ? f : kind2 === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||
};
|
||
var _AbstractPage_client;
|
||
async function defaultParseResponse(props) {
|
||
const { response } = props;
|
||
if (props.options.stream) {
|
||
debug("response", response.status, response.url, response.headers, response.body);
|
||
if (props.options.__streamClass) {
|
||
return props.options.__streamClass.fromSSEResponse(response, props.controller);
|
||
}
|
||
return Stream.fromSSEResponse(response, props.controller);
|
||
}
|
||
if (response.status === 204) {
|
||
return null;
|
||
}
|
||
if (props.options.__binaryResponse) {
|
||
return response;
|
||
}
|
||
const contentType = response.headers.get("content-type");
|
||
const isJSON = (contentType == null ? void 0 : contentType.includes("application/json")) || (contentType == null ? void 0 : contentType.includes("application/vnd.api+json"));
|
||
if (isJSON) {
|
||
const json = await response.json();
|
||
debug("response", response.status, response.url, response.headers, json);
|
||
return _addRequestID(json, response);
|
||
}
|
||
const text = await response.text();
|
||
debug("response", response.status, response.url, response.headers, text);
|
||
return text;
|
||
}
|
||
function _addRequestID(value, response) {
|
||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||
return value;
|
||
}
|
||
return Object.defineProperty(value, "_request_id", {
|
||
value: response.headers.get("x-request-id"),
|
||
enumerable: false
|
||
});
|
||
}
|
||
var APIPromise = class _APIPromise extends Promise {
|
||
constructor(responsePromise, parseResponse = defaultParseResponse) {
|
||
super((resolve) => {
|
||
resolve(null);
|
||
});
|
||
this.responsePromise = responsePromise;
|
||
this.parseResponse = parseResponse;
|
||
}
|
||
_thenUnwrap(transform) {
|
||
return new _APIPromise(this.responsePromise, async (props) => _addRequestID(transform(await this.parseResponse(props), props), props.response));
|
||
}
|
||
/**
|
||
* Gets the raw `Response` instance instead of parsing the response
|
||
* data.
|
||
*
|
||
* If you want to parse the response body but still get the `Response`
|
||
* instance, you can use {@link withResponse()}.
|
||
*
|
||
* 👋 Getting the wrong TypeScript type for `Response`?
|
||
* Try setting `"moduleResolution": "NodeNext"` if you can,
|
||
* or add one of these imports before your first `import … from 'openai'`:
|
||
* - `import 'openai/shims/node'` (if you're running on Node)
|
||
* - `import 'openai/shims/web'` (otherwise)
|
||
*/
|
||
asResponse() {
|
||
return this.responsePromise.then((p) => p.response);
|
||
}
|
||
/**
|
||
* Gets the parsed response data, the raw `Response` instance and the ID of the request,
|
||
* returned via the X-Request-ID header which is useful for debugging requests and reporting
|
||
* issues to OpenAI.
|
||
*
|
||
* If you just want to get the raw `Response` instance without parsing it,
|
||
* you can use {@link asResponse()}.
|
||
*
|
||
*
|
||
* 👋 Getting the wrong TypeScript type for `Response`?
|
||
* Try setting `"moduleResolution": "NodeNext"` if you can,
|
||
* or add one of these imports before your first `import … from 'openai'`:
|
||
* - `import 'openai/shims/node'` (if you're running on Node)
|
||
* - `import 'openai/shims/web'` (otherwise)
|
||
*/
|
||
async withResponse() {
|
||
const [data, response] = await Promise.all([this.parse(), this.asResponse()]);
|
||
return { data, response, request_id: response.headers.get("x-request-id") };
|
||
}
|
||
parse() {
|
||
if (!this.parsedPromise) {
|
||
this.parsedPromise = this.responsePromise.then(this.parseResponse);
|
||
}
|
||
return this.parsedPromise;
|
||
}
|
||
then(onfulfilled, onrejected) {
|
||
return this.parse().then(onfulfilled, onrejected);
|
||
}
|
||
catch(onrejected) {
|
||
return this.parse().catch(onrejected);
|
||
}
|
||
finally(onfinally) {
|
||
return this.parse().finally(onfinally);
|
||
}
|
||
};
|
||
var APIClient = class {
|
||
constructor({
|
||
baseURL,
|
||
maxRetries = 2,
|
||
timeout = 6e5,
|
||
// 10 minutes
|
||
httpAgent,
|
||
fetch: overridenFetch
|
||
}) {
|
||
this.baseURL = baseURL;
|
||
this.maxRetries = validatePositiveInteger("maxRetries", maxRetries);
|
||
this.timeout = validatePositiveInteger("timeout", timeout);
|
||
this.httpAgent = httpAgent;
|
||
this.fetch = overridenFetch != null ? overridenFetch : fetch2;
|
||
}
|
||
authHeaders(opts) {
|
||
return {};
|
||
}
|
||
/**
|
||
* Override this to add your own default headers, for example:
|
||
*
|
||
* {
|
||
* ...super.defaultHeaders(),
|
||
* Authorization: 'Bearer 123',
|
||
* }
|
||
*/
|
||
defaultHeaders(opts) {
|
||
return {
|
||
Accept: "application/json",
|
||
"Content-Type": "application/json",
|
||
"User-Agent": this.getUserAgent(),
|
||
...getPlatformHeaders(),
|
||
...this.authHeaders(opts)
|
||
};
|
||
}
|
||
/**
|
||
* Override this to add your own headers validation:
|
||
*/
|
||
validateHeaders(headers, customHeaders) {
|
||
}
|
||
defaultIdempotencyKey() {
|
||
return `stainless-node-retry-${uuid4()}`;
|
||
}
|
||
get(path, opts) {
|
||
return this.methodRequest("get", path, opts);
|
||
}
|
||
post(path, opts) {
|
||
return this.methodRequest("post", path, opts);
|
||
}
|
||
patch(path, opts) {
|
||
return this.methodRequest("patch", path, opts);
|
||
}
|
||
put(path, opts) {
|
||
return this.methodRequest("put", path, opts);
|
||
}
|
||
delete(path, opts) {
|
||
return this.methodRequest("delete", path, opts);
|
||
}
|
||
methodRequest(method, path, opts) {
|
||
return this.request(Promise.resolve(opts).then(async (opts2) => {
|
||
const body = opts2 && isBlobLike(opts2 == null ? void 0 : opts2.body) ? new DataView(await opts2.body.arrayBuffer()) : (opts2 == null ? void 0 : opts2.body) instanceof DataView ? opts2.body : (opts2 == null ? void 0 : opts2.body) instanceof ArrayBuffer ? new DataView(opts2.body) : opts2 && ArrayBuffer.isView(opts2 == null ? void 0 : opts2.body) ? new DataView(opts2.body.buffer) : opts2 == null ? void 0 : opts2.body;
|
||
return { method, path, ...opts2, body };
|
||
}));
|
||
}
|
||
getAPIList(path, Page2, opts) {
|
||
return this.requestAPIList(Page2, { method: "get", path, ...opts });
|
||
}
|
||
calculateContentLength(body) {
|
||
if (typeof body === "string") {
|
||
if (typeof Buffer !== "undefined") {
|
||
return Buffer.byteLength(body, "utf8").toString();
|
||
}
|
||
if (typeof TextEncoder !== "undefined") {
|
||
const encoder = new TextEncoder();
|
||
const encoded = encoder.encode(body);
|
||
return encoded.length.toString();
|
||
}
|
||
} else if (ArrayBuffer.isView(body)) {
|
||
return body.byteLength.toString();
|
||
}
|
||
return null;
|
||
}
|
||
buildRequest(options, { retryCount = 0 } = {}) {
|
||
var _a2, _b, _c, _d, _e, _f;
|
||
const { method, path, query, headers = {} } = options;
|
||
const body = ArrayBuffer.isView(options.body) || options.__binaryRequest && typeof options.body === "string" ? options.body : isMultipartBody(options.body) ? options.body.body : options.body ? JSON.stringify(options.body, null, 2) : null;
|
||
const contentLength = this.calculateContentLength(body);
|
||
const url = this.buildURL(path, query);
|
||
if ("timeout" in options)
|
||
validatePositiveInteger("timeout", options.timeout);
|
||
const timeout = (_a2 = options.timeout) != null ? _a2 : this.timeout;
|
||
const httpAgent = (_c = (_b = options.httpAgent) != null ? _b : this.httpAgent) != null ? _c : getDefaultAgent(url);
|
||
const minAgentTimeout = timeout + 1e3;
|
||
if (typeof ((_d = httpAgent == null ? void 0 : httpAgent.options) == null ? void 0 : _d.timeout) === "number" && minAgentTimeout > ((_e = httpAgent.options.timeout) != null ? _e : 0)) {
|
||
httpAgent.options.timeout = minAgentTimeout;
|
||
}
|
||
if (this.idempotencyHeader && method !== "get") {
|
||
if (!options.idempotencyKey)
|
||
options.idempotencyKey = this.defaultIdempotencyKey();
|
||
headers[this.idempotencyHeader] = options.idempotencyKey;
|
||
}
|
||
const reqHeaders = this.buildHeaders({ options, headers, contentLength, retryCount });
|
||
const req = {
|
||
method,
|
||
...body && { body },
|
||
headers: reqHeaders,
|
||
...httpAgent && { agent: httpAgent },
|
||
// @ts-ignore node-fetch uses a custom AbortSignal type that is
|
||
// not compatible with standard web types
|
||
signal: (_f = options.signal) != null ? _f : null
|
||
};
|
||
return { req, url, timeout };
|
||
}
|
||
buildHeaders({ options, headers, contentLength, retryCount }) {
|
||
const reqHeaders = {};
|
||
if (contentLength) {
|
||
reqHeaders["content-length"] = contentLength;
|
||
}
|
||
const defaultHeaders = this.defaultHeaders(options);
|
||
applyHeadersMut(reqHeaders, defaultHeaders);
|
||
applyHeadersMut(reqHeaders, headers);
|
||
if (isMultipartBody(options.body) && kind !== "node") {
|
||
delete reqHeaders["content-type"];
|
||
}
|
||
if (getHeader(defaultHeaders, "x-stainless-retry-count") === void 0 && getHeader(headers, "x-stainless-retry-count") === void 0) {
|
||
reqHeaders["x-stainless-retry-count"] = String(retryCount);
|
||
}
|
||
this.validateHeaders(reqHeaders, headers);
|
||
return reqHeaders;
|
||
}
|
||
/**
|
||
* Used as a callback for mutating the given `FinalRequestOptions` object.
|
||
*/
|
||
async prepareOptions(options) {
|
||
}
|
||
/**
|
||
* Used as a callback for mutating the given `RequestInit` object.
|
||
*
|
||
* This is useful for cases where you want to add certain headers based off of
|
||
* the request properties, e.g. `method` or `url`.
|
||
*/
|
||
async prepareRequest(request, { url, options }) {
|
||
}
|
||
parseHeaders(headers) {
|
||
return !headers ? {} : Symbol.iterator in headers ? Object.fromEntries(Array.from(headers).map((header) => [...header])) : { ...headers };
|
||
}
|
||
makeStatusError(status, error, message, headers) {
|
||
return APIError.generate(status, error, message, headers);
|
||
}
|
||
request(options, remainingRetries = null) {
|
||
return new APIPromise(this.makeRequest(options, remainingRetries));
|
||
}
|
||
async makeRequest(optionsInput, retriesRemaining) {
|
||
var _a2, _b, _c;
|
||
const options = await optionsInput;
|
||
const maxRetries = (_a2 = options.maxRetries) != null ? _a2 : this.maxRetries;
|
||
if (retriesRemaining == null) {
|
||
retriesRemaining = maxRetries;
|
||
}
|
||
await this.prepareOptions(options);
|
||
const { req, url, timeout } = this.buildRequest(options, { retryCount: maxRetries - retriesRemaining });
|
||
await this.prepareRequest(req, { url, options });
|
||
debug("request", url, options, req.headers);
|
||
if ((_b = options.signal) == null ? void 0 : _b.aborted) {
|
||
throw new APIUserAbortError();
|
||
}
|
||
const controller = new AbortController();
|
||
const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
|
||
if (response instanceof Error) {
|
||
if ((_c = options.signal) == null ? void 0 : _c.aborted) {
|
||
throw new APIUserAbortError();
|
||
}
|
||
if (retriesRemaining) {
|
||
return this.retryRequest(options, retriesRemaining);
|
||
}
|
||
if (response.name === "AbortError") {
|
||
throw new APIConnectionTimeoutError();
|
||
}
|
||
throw new APIConnectionError({ cause: response });
|
||
}
|
||
const responseHeaders = createResponseHeaders(response.headers);
|
||
if (!response.ok) {
|
||
if (retriesRemaining && this.shouldRetry(response)) {
|
||
const retryMessage2 = `retrying, ${retriesRemaining} attempts remaining`;
|
||
debug(`response (error; ${retryMessage2})`, response.status, url, responseHeaders);
|
||
return this.retryRequest(options, retriesRemaining, responseHeaders);
|
||
}
|
||
const errText = await response.text().catch((e) => castToError(e).message);
|
||
const errJSON = safeJSON(errText);
|
||
const errMessage = errJSON ? void 0 : errText;
|
||
const retryMessage = retriesRemaining ? `(error; no more retries left)` : `(error; not retryable)`;
|
||
debug(`response (error; ${retryMessage})`, response.status, url, responseHeaders, errMessage);
|
||
const err = this.makeStatusError(response.status, errJSON, errMessage, responseHeaders);
|
||
throw err;
|
||
}
|
||
return { response, options, controller };
|
||
}
|
||
requestAPIList(Page2, options) {
|
||
const request = this.makeRequest(options, null);
|
||
return new PagePromise(this, request, Page2);
|
||
}
|
||
buildURL(path, query) {
|
||
const url = isAbsoluteURL(path) ? new URL(path) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path.startsWith("/") ? path.slice(1) : path));
|
||
const defaultQuery = this.defaultQuery();
|
||
if (!isEmptyObj(defaultQuery)) {
|
||
query = { ...defaultQuery, ...query };
|
||
}
|
||
if (typeof query === "object" && query && !Array.isArray(query)) {
|
||
url.search = this.stringifyQuery(query);
|
||
}
|
||
return url.toString();
|
||
}
|
||
stringifyQuery(query) {
|
||
return Object.entries(query).filter(([_, value]) => typeof value !== "undefined").map(([key, value]) => {
|
||
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
||
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||
}
|
||
if (value === null) {
|
||
return `${encodeURIComponent(key)}=`;
|
||
}
|
||
throw new OpenAIError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`);
|
||
}).join("&");
|
||
}
|
||
async fetchWithTimeout(url, init, ms, controller) {
|
||
const { signal, ...options } = init || {};
|
||
if (signal)
|
||
signal.addEventListener("abort", () => controller.abort());
|
||
const timeout = setTimeout(() => controller.abort(), ms);
|
||
return (
|
||
// use undefined this binding; fetch errors if bound to something else in browser/cloudflare
|
||
this.fetch.call(void 0, url, { signal: controller.signal, ...options }).finally(() => {
|
||
clearTimeout(timeout);
|
||
})
|
||
);
|
||
}
|
||
shouldRetry(response) {
|
||
const shouldRetryHeader = response.headers.get("x-should-retry");
|
||
if (shouldRetryHeader === "true")
|
||
return true;
|
||
if (shouldRetryHeader === "false")
|
||
return false;
|
||
if (response.status === 408)
|
||
return true;
|
||
if (response.status === 409)
|
||
return true;
|
||
if (response.status === 429)
|
||
return true;
|
||
if (response.status >= 500)
|
||
return true;
|
||
return false;
|
||
}
|
||
async retryRequest(options, retriesRemaining, responseHeaders) {
|
||
var _a2;
|
||
let timeoutMillis;
|
||
const retryAfterMillisHeader = responseHeaders == null ? void 0 : responseHeaders["retry-after-ms"];
|
||
if (retryAfterMillisHeader) {
|
||
const timeoutMs = parseFloat(retryAfterMillisHeader);
|
||
if (!Number.isNaN(timeoutMs)) {
|
||
timeoutMillis = timeoutMs;
|
||
}
|
||
}
|
||
const retryAfterHeader = responseHeaders == null ? void 0 : responseHeaders["retry-after"];
|
||
if (retryAfterHeader && !timeoutMillis) {
|
||
const timeoutSeconds = parseFloat(retryAfterHeader);
|
||
if (!Number.isNaN(timeoutSeconds)) {
|
||
timeoutMillis = timeoutSeconds * 1e3;
|
||
} else {
|
||
timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
|
||
}
|
||
}
|
||
if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1e3)) {
|
||
const maxRetries = (_a2 = options.maxRetries) != null ? _a2 : this.maxRetries;
|
||
timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
|
||
}
|
||
await sleep(timeoutMillis);
|
||
return this.makeRequest(options, retriesRemaining - 1);
|
||
}
|
||
calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) {
|
||
const initialRetryDelay = 0.5;
|
||
const maxRetryDelay = 8;
|
||
const numRetries = maxRetries - retriesRemaining;
|
||
const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);
|
||
const jitter = 1 - Math.random() * 0.25;
|
||
return sleepSeconds * jitter * 1e3;
|
||
}
|
||
getUserAgent() {
|
||
return `${this.constructor.name}/JS ${VERSION}`;
|
||
}
|
||
};
|
||
var AbstractPage = class {
|
||
constructor(client, response, body, options) {
|
||
_AbstractPage_client.set(this, void 0);
|
||
__classPrivateFieldSet(this, _AbstractPage_client, client, "f");
|
||
this.options = options;
|
||
this.response = response;
|
||
this.body = body;
|
||
}
|
||
hasNextPage() {
|
||
const items = this.getPaginatedItems();
|
||
if (!items.length)
|
||
return false;
|
||
return this.nextPageInfo() != null;
|
||
}
|
||
async getNextPage() {
|
||
const nextInfo = this.nextPageInfo();
|
||
if (!nextInfo) {
|
||
throw new OpenAIError("No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.");
|
||
}
|
||
const nextOptions = { ...this.options };
|
||
if ("params" in nextInfo && typeof nextOptions.query === "object") {
|
||
nextOptions.query = { ...nextOptions.query, ...nextInfo.params };
|
||
} else if ("url" in nextInfo) {
|
||
const params = [...Object.entries(nextOptions.query || {}), ...nextInfo.url.searchParams.entries()];
|
||
for (const [key, value] of params) {
|
||
nextInfo.url.searchParams.set(key, value);
|
||
}
|
||
nextOptions.query = void 0;
|
||
nextOptions.path = nextInfo.url.toString();
|
||
}
|
||
return await __classPrivateFieldGet(this, _AbstractPage_client, "f").requestAPIList(this.constructor, nextOptions);
|
||
}
|
||
async *iterPages() {
|
||
let page = this;
|
||
yield page;
|
||
while (page.hasNextPage()) {
|
||
page = await page.getNextPage();
|
||
yield page;
|
||
}
|
||
}
|
||
async *[(_AbstractPage_client = /* @__PURE__ */ new WeakMap(), Symbol.asyncIterator)]() {
|
||
for await (const page of this.iterPages()) {
|
||
for (const item of page.getPaginatedItems()) {
|
||
yield item;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
var PagePromise = class extends APIPromise {
|
||
constructor(client, request, Page2) {
|
||
super(request, async (props) => new Page2(client, props.response, await defaultParseResponse(props), props.options));
|
||
}
|
||
/**
|
||
* Allow auto-paginating iteration on an unawaited list call, eg:
|
||
*
|
||
* for await (const item of client.items.list()) {
|
||
* console.log(item)
|
||
* }
|
||
*/
|
||
async *[Symbol.asyncIterator]() {
|
||
const page = await this;
|
||
for await (const item of page) {
|
||
yield item;
|
||
}
|
||
}
|
||
};
|
||
var createResponseHeaders = (headers) => {
|
||
return new Proxy(Object.fromEntries(
|
||
// @ts-ignore
|
||
headers.entries()
|
||
), {
|
||
get(target, name) {
|
||
const key = name.toString();
|
||
return target[key.toLowerCase()] || target[key];
|
||
}
|
||
});
|
||
};
|
||
var requestOptionsKeys = {
|
||
method: true,
|
||
path: true,
|
||
query: true,
|
||
body: true,
|
||
headers: true,
|
||
maxRetries: true,
|
||
stream: true,
|
||
timeout: true,
|
||
httpAgent: true,
|
||
signal: true,
|
||
idempotencyKey: true,
|
||
__binaryRequest: true,
|
||
__binaryResponse: true,
|
||
__streamClass: true
|
||
};
|
||
var isRequestOptions = (obj) => {
|
||
return typeof obj === "object" && obj !== null && !isEmptyObj(obj) && Object.keys(obj).every((k) => hasOwn(requestOptionsKeys, k));
|
||
};
|
||
var getPlatformProperties = () => {
|
||
var _a2, _b;
|
||
if (typeof Deno !== "undefined" && Deno.build != null) {
|
||
return {
|
||
"X-Stainless-Lang": "js",
|
||
"X-Stainless-Package-Version": VERSION,
|
||
"X-Stainless-OS": normalizePlatform(Deno.build.os),
|
||
"X-Stainless-Arch": normalizeArch(Deno.build.arch),
|
||
"X-Stainless-Runtime": "deno",
|
||
"X-Stainless-Runtime-Version": typeof Deno.version === "string" ? Deno.version : (_b = (_a2 = Deno.version) == null ? void 0 : _a2.deno) != null ? _b : "unknown"
|
||
};
|
||
}
|
||
if (typeof EdgeRuntime !== "undefined") {
|
||
return {
|
||
"X-Stainless-Lang": "js",
|
||
"X-Stainless-Package-Version": VERSION,
|
||
"X-Stainless-OS": "Unknown",
|
||
"X-Stainless-Arch": `other:${EdgeRuntime}`,
|
||
"X-Stainless-Runtime": "edge",
|
||
"X-Stainless-Runtime-Version": process.version
|
||
};
|
||
}
|
||
if (Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]") {
|
||
return {
|
||
"X-Stainless-Lang": "js",
|
||
"X-Stainless-Package-Version": VERSION,
|
||
"X-Stainless-OS": normalizePlatform(process.platform),
|
||
"X-Stainless-Arch": normalizeArch(process.arch),
|
||
"X-Stainless-Runtime": "node",
|
||
"X-Stainless-Runtime-Version": process.version
|
||
};
|
||
}
|
||
const browserInfo = getBrowserInfo();
|
||
if (browserInfo) {
|
||
return {
|
||
"X-Stainless-Lang": "js",
|
||
"X-Stainless-Package-Version": VERSION,
|
||
"X-Stainless-OS": "Unknown",
|
||
"X-Stainless-Arch": "unknown",
|
||
"X-Stainless-Runtime": `browser:${browserInfo.browser}`,
|
||
"X-Stainless-Runtime-Version": browserInfo.version
|
||
};
|
||
}
|
||
return {
|
||
"X-Stainless-Lang": "js",
|
||
"X-Stainless-Package-Version": VERSION,
|
||
"X-Stainless-OS": "Unknown",
|
||
"X-Stainless-Arch": "unknown",
|
||
"X-Stainless-Runtime": "unknown",
|
||
"X-Stainless-Runtime-Version": "unknown"
|
||
};
|
||
};
|
||
function getBrowserInfo() {
|
||
if (typeof navigator === "undefined" || !navigator) {
|
||
return null;
|
||
}
|
||
const browserPatterns = [
|
||
{ key: "edge", pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||
{ key: "ie", pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||
{ key: "ie", pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||
{ key: "chrome", pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||
{ key: "firefox", pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||
{ key: "safari", pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }
|
||
];
|
||
for (const { key, pattern } of browserPatterns) {
|
||
const match = pattern.exec(navigator.userAgent);
|
||
if (match) {
|
||
const major = match[1] || 0;
|
||
const minor = match[2] || 0;
|
||
const patch = match[3] || 0;
|
||
return { browser: key, version: `${major}.${minor}.${patch}` };
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
var normalizeArch = (arch) => {
|
||
if (arch === "x32")
|
||
return "x32";
|
||
if (arch === "x86_64" || arch === "x64")
|
||
return "x64";
|
||
if (arch === "arm")
|
||
return "arm";
|
||
if (arch === "aarch64" || arch === "arm64")
|
||
return "arm64";
|
||
if (arch)
|
||
return `other:${arch}`;
|
||
return "unknown";
|
||
};
|
||
var normalizePlatform = (platform) => {
|
||
platform = platform.toLowerCase();
|
||
if (platform.includes("ios"))
|
||
return "iOS";
|
||
if (platform === "android")
|
||
return "Android";
|
||
if (platform === "darwin")
|
||
return "MacOS";
|
||
if (platform === "win32")
|
||
return "Windows";
|
||
if (platform === "freebsd")
|
||
return "FreeBSD";
|
||
if (platform === "openbsd")
|
||
return "OpenBSD";
|
||
if (platform === "linux")
|
||
return "Linux";
|
||
if (platform)
|
||
return `Other:${platform}`;
|
||
return "Unknown";
|
||
};
|
||
var _platformHeaders;
|
||
var getPlatformHeaders = () => {
|
||
return _platformHeaders != null ? _platformHeaders : _platformHeaders = getPlatformProperties();
|
||
};
|
||
var safeJSON = (text) => {
|
||
try {
|
||
return JSON.parse(text);
|
||
} catch (err) {
|
||
return void 0;
|
||
}
|
||
};
|
||
var startsWithSchemeRegexp = new RegExp("^(?:[a-z]+:)?//", "i");
|
||
var isAbsoluteURL = (url) => {
|
||
return startsWithSchemeRegexp.test(url);
|
||
};
|
||
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||
var validatePositiveInteger = (name, n) => {
|
||
if (typeof n !== "number" || !Number.isInteger(n)) {
|
||
throw new OpenAIError(`${name} must be an integer`);
|
||
}
|
||
if (n < 0) {
|
||
throw new OpenAIError(`${name} must be a positive integer`);
|
||
}
|
||
return n;
|
||
};
|
||
var castToError = (err) => {
|
||
if (err instanceof Error)
|
||
return err;
|
||
if (typeof err === "object" && err !== null) {
|
||
try {
|
||
return new Error(JSON.stringify(err));
|
||
} catch (e) {
|
||
}
|
||
}
|
||
return new Error(err);
|
||
};
|
||
var readEnv = (env) => {
|
||
var _a2, _b, _c, _d, _e, _f;
|
||
if (typeof process !== "undefined") {
|
||
return (_c = (_b = (_a2 = process.env) == null ? void 0 : _a2[env]) == null ? void 0 : _b.trim()) != null ? _c : void 0;
|
||
}
|
||
if (typeof Deno !== "undefined") {
|
||
return (_f = (_e = (_d = Deno.env) == null ? void 0 : _d.get) == null ? void 0 : _e.call(_d, env)) == null ? void 0 : _f.trim();
|
||
}
|
||
return void 0;
|
||
};
|
||
function isEmptyObj(obj) {
|
||
if (!obj)
|
||
return true;
|
||
for (const _k in obj)
|
||
return false;
|
||
return true;
|
||
}
|
||
function hasOwn(obj, key) {
|
||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||
}
|
||
function applyHeadersMut(targetHeaders, newHeaders) {
|
||
for (const k in newHeaders) {
|
||
if (!hasOwn(newHeaders, k))
|
||
continue;
|
||
const lowerKey = k.toLowerCase();
|
||
if (!lowerKey)
|
||
continue;
|
||
const val = newHeaders[k];
|
||
if (val === null) {
|
||
delete targetHeaders[lowerKey];
|
||
} else if (val !== void 0) {
|
||
targetHeaders[lowerKey] = val;
|
||
}
|
||
}
|
||
}
|
||
function debug(action, ...args) {
|
||
var _a2;
|
||
if (typeof process !== "undefined" && ((_a2 = process == null ? void 0 : process.env) == null ? void 0 : _a2["DEBUG"]) === "true") {
|
||
console.log(`OpenAI:DEBUG:${action}`, ...args);
|
||
}
|
||
}
|
||
var uuid4 = () => {
|
||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
||
const r = Math.random() * 16 | 0;
|
||
const v = c === "x" ? r : r & 3 | 8;
|
||
return v.toString(16);
|
||
});
|
||
};
|
||
var isRunningInBrowser = () => {
|
||
return (
|
||
// @ts-ignore
|
||
typeof window !== "undefined" && // @ts-ignore
|
||
typeof window.document !== "undefined" && // @ts-ignore
|
||
typeof navigator !== "undefined"
|
||
);
|
||
};
|
||
var isHeadersProtocol = (headers) => {
|
||
return typeof (headers == null ? void 0 : headers.get) === "function";
|
||
};
|
||
var getHeader = (headers, header) => {
|
||
var _a2;
|
||
const lowerCasedHeader = header.toLowerCase();
|
||
if (isHeadersProtocol(headers)) {
|
||
const intercapsHeader = ((_a2 = header[0]) == null ? void 0 : _a2.toUpperCase()) + header.substring(1).replace(/([^\w])(\w)/g, (_m, g1, g2) => g1 + g2.toUpperCase());
|
||
for (const key of [header, lowerCasedHeader, header.toUpperCase(), intercapsHeader]) {
|
||
const value = headers.get(key);
|
||
if (value) {
|
||
return value;
|
||
}
|
||
}
|
||
}
|
||
for (const [key, value] of Object.entries(headers)) {
|
||
if (key.toLowerCase() === lowerCasedHeader) {
|
||
if (Array.isArray(value)) {
|
||
if (value.length <= 1)
|
||
return value[0];
|
||
console.warn(`Received ${value.length} entries for the ${header} header, using the first entry.`);
|
||
return value[0];
|
||
}
|
||
return value;
|
||
}
|
||
}
|
||
return void 0;
|
||
};
|
||
function isObj(obj) {
|
||
return obj != null && typeof obj === "object" && !Array.isArray(obj);
|
||
}
|
||
|
||
// node_modules/openai/pagination.mjs
|
||
var Page = class extends AbstractPage {
|
||
constructor(client, response, body, options) {
|
||
super(client, response, body, options);
|
||
this.data = body.data || [];
|
||
this.object = body.object;
|
||
}
|
||
getPaginatedItems() {
|
||
var _a2;
|
||
return (_a2 = this.data) != null ? _a2 : [];
|
||
}
|
||
// @deprecated Please use `nextPageInfo()` instead
|
||
/**
|
||
* This page represents a response that isn't actually paginated at the API level
|
||
* so there will never be any next page params.
|
||
*/
|
||
nextPageParams() {
|
||
return null;
|
||
}
|
||
nextPageInfo() {
|
||
return null;
|
||
}
|
||
};
|
||
var CursorPage = class extends AbstractPage {
|
||
constructor(client, response, body, options) {
|
||
super(client, response, body, options);
|
||
this.data = body.data || [];
|
||
}
|
||
getPaginatedItems() {
|
||
var _a2;
|
||
return (_a2 = this.data) != null ? _a2 : [];
|
||
}
|
||
// @deprecated Please use `nextPageInfo()` instead
|
||
nextPageParams() {
|
||
const info = this.nextPageInfo();
|
||
if (!info)
|
||
return null;
|
||
if ("params" in info)
|
||
return info.params;
|
||
const params = Object.fromEntries(info.url.searchParams);
|
||
if (!Object.keys(params).length)
|
||
return null;
|
||
return params;
|
||
}
|
||
nextPageInfo() {
|
||
var _a2;
|
||
const data = this.getPaginatedItems();
|
||
if (!data.length) {
|
||
return null;
|
||
}
|
||
const id = (_a2 = data[data.length - 1]) == null ? void 0 : _a2.id;
|
||
if (!id) {
|
||
return null;
|
||
}
|
||
return { params: { after: id } };
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resource.mjs
|
||
var APIResource = class {
|
||
constructor(client) {
|
||
this._client = client;
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/chat/completions.mjs
|
||
var Completions = class extends APIResource {
|
||
create(body, options) {
|
||
var _a2;
|
||
return this._client.post("/chat/completions", { body, ...options, stream: (_a2 = body.stream) != null ? _a2 : false });
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/chat/chat.mjs
|
||
var Chat = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.completions = new Completions(this._client);
|
||
}
|
||
};
|
||
Chat.Completions = Completions;
|
||
|
||
// node_modules/openai/resources/audio/speech.mjs
|
||
var Speech = class extends APIResource {
|
||
/**
|
||
* Generates audio from the input text.
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/audio/speech", { body, ...options, __binaryResponse: true });
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/audio/transcriptions.mjs
|
||
var Transcriptions = class extends APIResource {
|
||
create(body, options) {
|
||
return this._client.post("/audio/transcriptions", multipartFormRequestOptions({ body, ...options }));
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/audio/translations.mjs
|
||
var Translations = class extends APIResource {
|
||
create(body, options) {
|
||
return this._client.post("/audio/translations", multipartFormRequestOptions({ body, ...options }));
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/audio/audio.mjs
|
||
var Audio = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.transcriptions = new Transcriptions(this._client);
|
||
this.translations = new Translations(this._client);
|
||
this.speech = new Speech(this._client);
|
||
}
|
||
};
|
||
Audio.Transcriptions = Transcriptions;
|
||
Audio.Translations = Translations;
|
||
Audio.Speech = Speech;
|
||
|
||
// node_modules/openai/resources/batches.mjs
|
||
var Batches = class extends APIResource {
|
||
/**
|
||
* Creates and executes a batch from an uploaded file of requests
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/batches", { body, ...options });
|
||
}
|
||
/**
|
||
* Retrieves a batch.
|
||
*/
|
||
retrieve(batchId, options) {
|
||
return this._client.get(`/batches/${batchId}`, options);
|
||
}
|
||
list(query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list({}, query);
|
||
}
|
||
return this._client.getAPIList("/batches", BatchesPage, { query, ...options });
|
||
}
|
||
/**
|
||
* Cancels an in-progress batch. The batch will be in status `cancelling` for up to
|
||
* 10 minutes, before changing to `cancelled`, where it will have partial results
|
||
* (if any) available in the output file.
|
||
*/
|
||
cancel(batchId, options) {
|
||
return this._client.post(`/batches/${batchId}/cancel`, options);
|
||
}
|
||
};
|
||
var BatchesPage = class extends CursorPage {
|
||
};
|
||
Batches.BatchesPage = BatchesPage;
|
||
|
||
// node_modules/openai/resources/beta/assistants.mjs
|
||
var Assistants = class extends APIResource {
|
||
/**
|
||
* Create an assistant with a model and instructions.
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/assistants", {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Retrieves an assistant.
|
||
*/
|
||
retrieve(assistantId, options) {
|
||
return this._client.get(`/assistants/${assistantId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Modifies an assistant.
|
||
*/
|
||
update(assistantId, body, options) {
|
||
return this._client.post(`/assistants/${assistantId}`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
list(query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list({}, query);
|
||
}
|
||
return this._client.getAPIList("/assistants", AssistantsPage, {
|
||
query,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Delete an assistant.
|
||
*/
|
||
del(assistantId, options) {
|
||
return this._client.delete(`/assistants/${assistantId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
};
|
||
var AssistantsPage = class extends CursorPage {
|
||
};
|
||
Assistants.AssistantsPage = AssistantsPage;
|
||
|
||
// node_modules/openai/lib/RunnableFunction.mjs
|
||
function isRunnableFunctionWithParse(fn) {
|
||
return typeof fn.parse === "function";
|
||
}
|
||
|
||
// node_modules/openai/lib/chatCompletionUtils.mjs
|
||
var isAssistantMessage = (message) => {
|
||
return (message == null ? void 0 : message.role) === "assistant";
|
||
};
|
||
var isFunctionMessage = (message) => {
|
||
return (message == null ? void 0 : message.role) === "function";
|
||
};
|
||
var isToolMessage = (message) => {
|
||
return (message == null ? void 0 : message.role) === "tool";
|
||
};
|
||
|
||
// node_modules/openai/lib/EventStream.mjs
|
||
var __classPrivateFieldSet2 = function(receiver, state, value, kind2, f) {
|
||
if (kind2 === "m")
|
||
throw new TypeError("Private method is not writable");
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a setter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
||
return kind2 === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
|
||
};
|
||
var __classPrivateFieldGet2 = function(receiver, state, kind2, f) {
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a getter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||
return kind2 === "m" ? f : kind2 === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||
};
|
||
var _EventStream_instances;
|
||
var _EventStream_connectedPromise;
|
||
var _EventStream_resolveConnectedPromise;
|
||
var _EventStream_rejectConnectedPromise;
|
||
var _EventStream_endPromise;
|
||
var _EventStream_resolveEndPromise;
|
||
var _EventStream_rejectEndPromise;
|
||
var _EventStream_listeners;
|
||
var _EventStream_ended;
|
||
var _EventStream_errored;
|
||
var _EventStream_aborted;
|
||
var _EventStream_catchingPromiseCreated;
|
||
var _EventStream_handleError;
|
||
var EventStream = class {
|
||
constructor() {
|
||
_EventStream_instances.add(this);
|
||
this.controller = new AbortController();
|
||
_EventStream_connectedPromise.set(this, void 0);
|
||
_EventStream_resolveConnectedPromise.set(this, () => {
|
||
});
|
||
_EventStream_rejectConnectedPromise.set(this, () => {
|
||
});
|
||
_EventStream_endPromise.set(this, void 0);
|
||
_EventStream_resolveEndPromise.set(this, () => {
|
||
});
|
||
_EventStream_rejectEndPromise.set(this, () => {
|
||
});
|
||
_EventStream_listeners.set(this, {});
|
||
_EventStream_ended.set(this, false);
|
||
_EventStream_errored.set(this, false);
|
||
_EventStream_aborted.set(this, false);
|
||
_EventStream_catchingPromiseCreated.set(this, false);
|
||
__classPrivateFieldSet2(this, _EventStream_connectedPromise, new Promise((resolve, reject) => {
|
||
__classPrivateFieldSet2(this, _EventStream_resolveConnectedPromise, resolve, "f");
|
||
__classPrivateFieldSet2(this, _EventStream_rejectConnectedPromise, reject, "f");
|
||
}), "f");
|
||
__classPrivateFieldSet2(this, _EventStream_endPromise, new Promise((resolve, reject) => {
|
||
__classPrivateFieldSet2(this, _EventStream_resolveEndPromise, resolve, "f");
|
||
__classPrivateFieldSet2(this, _EventStream_rejectEndPromise, reject, "f");
|
||
}), "f");
|
||
__classPrivateFieldGet2(this, _EventStream_connectedPromise, "f").catch(() => {
|
||
});
|
||
__classPrivateFieldGet2(this, _EventStream_endPromise, "f").catch(() => {
|
||
});
|
||
}
|
||
_run(executor) {
|
||
setTimeout(() => {
|
||
executor().then(() => {
|
||
this._emitFinal();
|
||
this._emit("end");
|
||
}, __classPrivateFieldGet2(this, _EventStream_instances, "m", _EventStream_handleError).bind(this));
|
||
}, 0);
|
||
}
|
||
_connected() {
|
||
if (this.ended)
|
||
return;
|
||
__classPrivateFieldGet2(this, _EventStream_resolveConnectedPromise, "f").call(this);
|
||
this._emit("connect");
|
||
}
|
||
get ended() {
|
||
return __classPrivateFieldGet2(this, _EventStream_ended, "f");
|
||
}
|
||
get errored() {
|
||
return __classPrivateFieldGet2(this, _EventStream_errored, "f");
|
||
}
|
||
get aborted() {
|
||
return __classPrivateFieldGet2(this, _EventStream_aborted, "f");
|
||
}
|
||
abort() {
|
||
this.controller.abort();
|
||
}
|
||
/**
|
||
* Adds the listener function to the end of the listeners array for the event.
|
||
* No checks are made to see if the listener has already been added. Multiple calls passing
|
||
* the same combination of event and listener will result in the listener being added, and
|
||
* called, multiple times.
|
||
* @returns this ChatCompletionStream, so that calls can be chained
|
||
*/
|
||
on(event, listener) {
|
||
const listeners = __classPrivateFieldGet2(this, _EventStream_listeners, "f")[event] || (__classPrivateFieldGet2(this, _EventStream_listeners, "f")[event] = []);
|
||
listeners.push({ listener });
|
||
return this;
|
||
}
|
||
/**
|
||
* Removes the specified listener from the listener array for the event.
|
||
* off() will remove, at most, one instance of a listener from the listener array. If any single
|
||
* listener has been added multiple times to the listener array for the specified event, then
|
||
* off() must be called multiple times to remove each instance.
|
||
* @returns this ChatCompletionStream, so that calls can be chained
|
||
*/
|
||
off(event, listener) {
|
||
const listeners = __classPrivateFieldGet2(this, _EventStream_listeners, "f")[event];
|
||
if (!listeners)
|
||
return this;
|
||
const index = listeners.findIndex((l) => l.listener === listener);
|
||
if (index >= 0)
|
||
listeners.splice(index, 1);
|
||
return this;
|
||
}
|
||
/**
|
||
* Adds a one-time listener function for the event. The next time the event is triggered,
|
||
* this listener is removed and then invoked.
|
||
* @returns this ChatCompletionStream, so that calls can be chained
|
||
*/
|
||
once(event, listener) {
|
||
const listeners = __classPrivateFieldGet2(this, _EventStream_listeners, "f")[event] || (__classPrivateFieldGet2(this, _EventStream_listeners, "f")[event] = []);
|
||
listeners.push({ listener, once: true });
|
||
return this;
|
||
}
|
||
/**
|
||
* This is similar to `.once()`, but returns a Promise that resolves the next time
|
||
* the event is triggered, instead of calling a listener callback.
|
||
* @returns a Promise that resolves the next time given event is triggered,
|
||
* or rejects if an error is emitted. (If you request the 'error' event,
|
||
* returns a promise that resolves with the error).
|
||
*
|
||
* Example:
|
||
*
|
||
* const message = await stream.emitted('message') // rejects if the stream errors
|
||
*/
|
||
emitted(event) {
|
||
return new Promise((resolve, reject) => {
|
||
__classPrivateFieldSet2(this, _EventStream_catchingPromiseCreated, true, "f");
|
||
if (event !== "error")
|
||
this.once("error", reject);
|
||
this.once(event, resolve);
|
||
});
|
||
}
|
||
async done() {
|
||
__classPrivateFieldSet2(this, _EventStream_catchingPromiseCreated, true, "f");
|
||
await __classPrivateFieldGet2(this, _EventStream_endPromise, "f");
|
||
}
|
||
_emit(event, ...args) {
|
||
if (__classPrivateFieldGet2(this, _EventStream_ended, "f")) {
|
||
return;
|
||
}
|
||
if (event === "end") {
|
||
__classPrivateFieldSet2(this, _EventStream_ended, true, "f");
|
||
__classPrivateFieldGet2(this, _EventStream_resolveEndPromise, "f").call(this);
|
||
}
|
||
const listeners = __classPrivateFieldGet2(this, _EventStream_listeners, "f")[event];
|
||
if (listeners) {
|
||
__classPrivateFieldGet2(this, _EventStream_listeners, "f")[event] = listeners.filter((l) => !l.once);
|
||
listeners.forEach(({ listener }) => listener(...args));
|
||
}
|
||
if (event === "abort") {
|
||
const error = args[0];
|
||
if (!__classPrivateFieldGet2(this, _EventStream_catchingPromiseCreated, "f") && !(listeners == null ? void 0 : listeners.length)) {
|
||
Promise.reject(error);
|
||
}
|
||
__classPrivateFieldGet2(this, _EventStream_rejectConnectedPromise, "f").call(this, error);
|
||
__classPrivateFieldGet2(this, _EventStream_rejectEndPromise, "f").call(this, error);
|
||
this._emit("end");
|
||
return;
|
||
}
|
||
if (event === "error") {
|
||
const error = args[0];
|
||
if (!__classPrivateFieldGet2(this, _EventStream_catchingPromiseCreated, "f") && !(listeners == null ? void 0 : listeners.length)) {
|
||
Promise.reject(error);
|
||
}
|
||
__classPrivateFieldGet2(this, _EventStream_rejectConnectedPromise, "f").call(this, error);
|
||
__classPrivateFieldGet2(this, _EventStream_rejectEndPromise, "f").call(this, error);
|
||
this._emit("end");
|
||
}
|
||
}
|
||
_emitFinal() {
|
||
}
|
||
};
|
||
_EventStream_connectedPromise = /* @__PURE__ */ new WeakMap(), _EventStream_resolveConnectedPromise = /* @__PURE__ */ new WeakMap(), _EventStream_rejectConnectedPromise = /* @__PURE__ */ new WeakMap(), _EventStream_endPromise = /* @__PURE__ */ new WeakMap(), _EventStream_resolveEndPromise = /* @__PURE__ */ new WeakMap(), _EventStream_rejectEndPromise = /* @__PURE__ */ new WeakMap(), _EventStream_listeners = /* @__PURE__ */ new WeakMap(), _EventStream_ended = /* @__PURE__ */ new WeakMap(), _EventStream_errored = /* @__PURE__ */ new WeakMap(), _EventStream_aborted = /* @__PURE__ */ new WeakMap(), _EventStream_catchingPromiseCreated = /* @__PURE__ */ new WeakMap(), _EventStream_instances = /* @__PURE__ */ new WeakSet(), _EventStream_handleError = function _EventStream_handleError2(error) {
|
||
__classPrivateFieldSet2(this, _EventStream_errored, true, "f");
|
||
if (error instanceof Error && error.name === "AbortError") {
|
||
error = new APIUserAbortError();
|
||
}
|
||
if (error instanceof APIUserAbortError) {
|
||
__classPrivateFieldSet2(this, _EventStream_aborted, true, "f");
|
||
return this._emit("abort", error);
|
||
}
|
||
if (error instanceof OpenAIError) {
|
||
return this._emit("error", error);
|
||
}
|
||
if (error instanceof Error) {
|
||
const openAIError = new OpenAIError(error.message);
|
||
openAIError.cause = error;
|
||
return this._emit("error", openAIError);
|
||
}
|
||
return this._emit("error", new OpenAIError(String(error)));
|
||
};
|
||
|
||
// node_modules/openai/lib/parser.mjs
|
||
function isAutoParsableResponseFormat(response_format) {
|
||
return (response_format == null ? void 0 : response_format["$brand"]) === "auto-parseable-response-format";
|
||
}
|
||
function isAutoParsableTool(tool) {
|
||
return (tool == null ? void 0 : tool["$brand"]) === "auto-parseable-tool";
|
||
}
|
||
function maybeParseChatCompletion(completion, params) {
|
||
if (!params || !hasAutoParseableInput(params)) {
|
||
return {
|
||
...completion,
|
||
choices: completion.choices.map((choice) => {
|
||
var _a2;
|
||
return {
|
||
...choice,
|
||
message: { ...choice.message, parsed: null, tool_calls: (_a2 = choice.message.tool_calls) != null ? _a2 : [] }
|
||
};
|
||
})
|
||
};
|
||
}
|
||
return parseChatCompletion(completion, params);
|
||
}
|
||
function parseChatCompletion(completion, params) {
|
||
const choices = completion.choices.map((choice) => {
|
||
var _a2, _b;
|
||
if (choice.finish_reason === "length") {
|
||
throw new LengthFinishReasonError();
|
||
}
|
||
if (choice.finish_reason === "content_filter") {
|
||
throw new ContentFilterFinishReasonError();
|
||
}
|
||
return {
|
||
...choice,
|
||
message: {
|
||
...choice.message,
|
||
tool_calls: (_b = (_a2 = choice.message.tool_calls) == null ? void 0 : _a2.map((toolCall) => parseToolCall(params, toolCall))) != null ? _b : [],
|
||
parsed: choice.message.content && !choice.message.refusal ? parseResponseFormat(params, choice.message.content) : null
|
||
}
|
||
};
|
||
});
|
||
return { ...completion, choices };
|
||
}
|
||
function parseResponseFormat(params, content) {
|
||
var _a2, _b;
|
||
if (((_a2 = params.response_format) == null ? void 0 : _a2.type) !== "json_schema") {
|
||
return null;
|
||
}
|
||
if (((_b = params.response_format) == null ? void 0 : _b.type) === "json_schema") {
|
||
if ("$parseRaw" in params.response_format) {
|
||
const response_format = params.response_format;
|
||
return response_format.$parseRaw(content);
|
||
}
|
||
return JSON.parse(content);
|
||
}
|
||
return null;
|
||
}
|
||
function parseToolCall(params, toolCall) {
|
||
var _a2;
|
||
const inputTool = (_a2 = params.tools) == null ? void 0 : _a2.find((inputTool2) => {
|
||
var _a3;
|
||
return ((_a3 = inputTool2.function) == null ? void 0 : _a3.name) === toolCall.function.name;
|
||
});
|
||
return {
|
||
...toolCall,
|
||
function: {
|
||
...toolCall.function,
|
||
parsed_arguments: isAutoParsableTool(inputTool) ? inputTool.$parseRaw(toolCall.function.arguments) : (inputTool == null ? void 0 : inputTool.function.strict) ? JSON.parse(toolCall.function.arguments) : null
|
||
}
|
||
};
|
||
}
|
||
function shouldParseToolCall(params, toolCall) {
|
||
var _a2;
|
||
if (!params) {
|
||
return false;
|
||
}
|
||
const inputTool = (_a2 = params.tools) == null ? void 0 : _a2.find((inputTool2) => {
|
||
var _a3;
|
||
return ((_a3 = inputTool2.function) == null ? void 0 : _a3.name) === toolCall.function.name;
|
||
});
|
||
return isAutoParsableTool(inputTool) || (inputTool == null ? void 0 : inputTool.function.strict) || false;
|
||
}
|
||
function hasAutoParseableInput(params) {
|
||
var _a2, _b;
|
||
if (isAutoParsableResponseFormat(params.response_format)) {
|
||
return true;
|
||
}
|
||
return (_b = (_a2 = params.tools) == null ? void 0 : _a2.some((t) => isAutoParsableTool(t) || t.type === "function" && t.function.strict === true)) != null ? _b : false;
|
||
}
|
||
function validateInputTools(tools) {
|
||
for (const tool of tools != null ? tools : []) {
|
||
if (tool.type !== "function") {
|
||
throw new OpenAIError(`Currently only \`function\` tool types support auto-parsing; Received \`${tool.type}\``);
|
||
}
|
||
if (tool.function.strict !== true) {
|
||
throw new OpenAIError(`The \`${tool.function.name}\` tool is not marked with \`strict: true\`. Only strict function tools can be auto-parsed`);
|
||
}
|
||
}
|
||
}
|
||
|
||
// node_modules/openai/lib/AbstractChatCompletionRunner.mjs
|
||
var __classPrivateFieldGet3 = function(receiver, state, kind2, f) {
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a getter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||
return kind2 === "m" ? f : kind2 === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||
};
|
||
var _AbstractChatCompletionRunner_instances;
|
||
var _AbstractChatCompletionRunner_getFinalContent;
|
||
var _AbstractChatCompletionRunner_getFinalMessage;
|
||
var _AbstractChatCompletionRunner_getFinalFunctionCall;
|
||
var _AbstractChatCompletionRunner_getFinalFunctionCallResult;
|
||
var _AbstractChatCompletionRunner_calculateTotalUsage;
|
||
var _AbstractChatCompletionRunner_validateParams;
|
||
var _AbstractChatCompletionRunner_stringifyFunctionCallResult;
|
||
var DEFAULT_MAX_CHAT_COMPLETIONS = 10;
|
||
var AbstractChatCompletionRunner = class extends EventStream {
|
||
constructor() {
|
||
super(...arguments);
|
||
_AbstractChatCompletionRunner_instances.add(this);
|
||
this._chatCompletions = [];
|
||
this.messages = [];
|
||
}
|
||
_addChatCompletion(chatCompletion) {
|
||
var _a2;
|
||
this._chatCompletions.push(chatCompletion);
|
||
this._emit("chatCompletion", chatCompletion);
|
||
const message = (_a2 = chatCompletion.choices[0]) == null ? void 0 : _a2.message;
|
||
if (message)
|
||
this._addMessage(message);
|
||
return chatCompletion;
|
||
}
|
||
_addMessage(message, emit = true) {
|
||
if (!("content" in message))
|
||
message.content = null;
|
||
this.messages.push(message);
|
||
if (emit) {
|
||
this._emit("message", message);
|
||
if ((isFunctionMessage(message) || isToolMessage(message)) && message.content) {
|
||
this._emit("functionCallResult", message.content);
|
||
} else if (isAssistantMessage(message) && message.function_call) {
|
||
this._emit("functionCall", message.function_call);
|
||
} else if (isAssistantMessage(message) && message.tool_calls) {
|
||
for (const tool_call of message.tool_calls) {
|
||
if (tool_call.type === "function") {
|
||
this._emit("functionCall", tool_call.function);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* @returns a promise that resolves with the final ChatCompletion, or rejects
|
||
* if an error occurred or the stream ended prematurely without producing a ChatCompletion.
|
||
*/
|
||
async finalChatCompletion() {
|
||
await this.done();
|
||
const completion = this._chatCompletions[this._chatCompletions.length - 1];
|
||
if (!completion)
|
||
throw new OpenAIError("stream ended without producing a ChatCompletion");
|
||
return completion;
|
||
}
|
||
/**
|
||
* @returns a promise that resolves with the content of the final ChatCompletionMessage, or rejects
|
||
* if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage.
|
||
*/
|
||
async finalContent() {
|
||
await this.done();
|
||
return __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalContent).call(this);
|
||
}
|
||
/**
|
||
* @returns a promise that resolves with the the final assistant ChatCompletionMessage response,
|
||
* or rejects if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage.
|
||
*/
|
||
async finalMessage() {
|
||
await this.done();
|
||
return __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this);
|
||
}
|
||
/**
|
||
* @returns a promise that resolves with the content of the final FunctionCall, or rejects
|
||
* if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage.
|
||
*/
|
||
async finalFunctionCall() {
|
||
await this.done();
|
||
return __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCall).call(this);
|
||
}
|
||
async finalFunctionCallResult() {
|
||
await this.done();
|
||
return __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCallResult).call(this);
|
||
}
|
||
async totalUsage() {
|
||
await this.done();
|
||
return __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_calculateTotalUsage).call(this);
|
||
}
|
||
allChatCompletions() {
|
||
return [...this._chatCompletions];
|
||
}
|
||
_emitFinal() {
|
||
const completion = this._chatCompletions[this._chatCompletions.length - 1];
|
||
if (completion)
|
||
this._emit("finalChatCompletion", completion);
|
||
const finalMessage = __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this);
|
||
if (finalMessage)
|
||
this._emit("finalMessage", finalMessage);
|
||
const finalContent = __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalContent).call(this);
|
||
if (finalContent)
|
||
this._emit("finalContent", finalContent);
|
||
const finalFunctionCall = __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCall).call(this);
|
||
if (finalFunctionCall)
|
||
this._emit("finalFunctionCall", finalFunctionCall);
|
||
const finalFunctionCallResult = __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCallResult).call(this);
|
||
if (finalFunctionCallResult != null)
|
||
this._emit("finalFunctionCallResult", finalFunctionCallResult);
|
||
if (this._chatCompletions.some((c) => c.usage)) {
|
||
this._emit("totalUsage", __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_calculateTotalUsage).call(this));
|
||
}
|
||
}
|
||
async _createChatCompletion(client, params, options) {
|
||
const signal = options == null ? void 0 : options.signal;
|
||
if (signal) {
|
||
if (signal.aborted)
|
||
this.controller.abort();
|
||
signal.addEventListener("abort", () => this.controller.abort());
|
||
}
|
||
__classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_validateParams).call(this, params);
|
||
const chatCompletion = await client.chat.completions.create({ ...params, stream: false }, { ...options, signal: this.controller.signal });
|
||
this._connected();
|
||
return this._addChatCompletion(parseChatCompletion(chatCompletion, params));
|
||
}
|
||
async _runChatCompletion(client, params, options) {
|
||
for (const message of params.messages) {
|
||
this._addMessage(message, false);
|
||
}
|
||
return await this._createChatCompletion(client, params, options);
|
||
}
|
||
async _runFunctions(client, params, options) {
|
||
var _a2;
|
||
const role = "function";
|
||
const { function_call = "auto", stream, ...restParams } = params;
|
||
const singleFunctionToCall = typeof function_call !== "string" && (function_call == null ? void 0 : function_call.name);
|
||
const { maxChatCompletions = DEFAULT_MAX_CHAT_COMPLETIONS } = options || {};
|
||
const functionsByName = {};
|
||
for (const f of params.functions) {
|
||
functionsByName[f.name || f.function.name] = f;
|
||
}
|
||
const functions = params.functions.map((f) => ({
|
||
name: f.name || f.function.name,
|
||
parameters: f.parameters,
|
||
description: f.description
|
||
}));
|
||
for (const message of params.messages) {
|
||
this._addMessage(message, false);
|
||
}
|
||
for (let i = 0; i < maxChatCompletions; ++i) {
|
||
const chatCompletion = await this._createChatCompletion(client, {
|
||
...restParams,
|
||
function_call,
|
||
functions,
|
||
messages: [...this.messages]
|
||
}, options);
|
||
const message = (_a2 = chatCompletion.choices[0]) == null ? void 0 : _a2.message;
|
||
if (!message) {
|
||
throw new OpenAIError(`missing message in ChatCompletion response`);
|
||
}
|
||
if (!message.function_call)
|
||
return;
|
||
const { name, arguments: args } = message.function_call;
|
||
const fn = functionsByName[name];
|
||
if (!fn) {
|
||
const content2 = `Invalid function_call: ${JSON.stringify(name)}. Available options are: ${functions.map((f) => JSON.stringify(f.name)).join(", ")}. Please try again`;
|
||
this._addMessage({ role, name, content: content2 });
|
||
continue;
|
||
} else if (singleFunctionToCall && singleFunctionToCall !== name) {
|
||
const content2 = `Invalid function_call: ${JSON.stringify(name)}. ${JSON.stringify(singleFunctionToCall)} requested. Please try again`;
|
||
this._addMessage({ role, name, content: content2 });
|
||
continue;
|
||
}
|
||
let parsed;
|
||
try {
|
||
parsed = isRunnableFunctionWithParse(fn) ? await fn.parse(args) : args;
|
||
} catch (error) {
|
||
this._addMessage({
|
||
role,
|
||
name,
|
||
content: error instanceof Error ? error.message : String(error)
|
||
});
|
||
continue;
|
||
}
|
||
const rawContent = await fn.function(parsed, this);
|
||
const content = __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_stringifyFunctionCallResult).call(this, rawContent);
|
||
this._addMessage({ role, name, content });
|
||
if (singleFunctionToCall)
|
||
return;
|
||
}
|
||
}
|
||
async _runTools(client, params, options) {
|
||
var _a2, _b, _c;
|
||
const role = "tool";
|
||
const { tool_choice = "auto", stream, ...restParams } = params;
|
||
const singleFunctionToCall = typeof tool_choice !== "string" && ((_a2 = tool_choice == null ? void 0 : tool_choice.function) == null ? void 0 : _a2.name);
|
||
const { maxChatCompletions = DEFAULT_MAX_CHAT_COMPLETIONS } = options || {};
|
||
const inputTools = params.tools.map((tool) => {
|
||
if (isAutoParsableTool(tool)) {
|
||
if (!tool.$callback) {
|
||
throw new OpenAIError("Tool given to `.runTools()` that does not have an associated function");
|
||
}
|
||
return {
|
||
type: "function",
|
||
function: {
|
||
function: tool.$callback,
|
||
name: tool.function.name,
|
||
description: tool.function.description || "",
|
||
parameters: tool.function.parameters,
|
||
parse: tool.$parseRaw,
|
||
strict: true
|
||
}
|
||
};
|
||
}
|
||
return tool;
|
||
});
|
||
const functionsByName = {};
|
||
for (const f of inputTools) {
|
||
if (f.type === "function") {
|
||
functionsByName[f.function.name || f.function.function.name] = f.function;
|
||
}
|
||
}
|
||
const tools = "tools" in params ? inputTools.map((t) => t.type === "function" ? {
|
||
type: "function",
|
||
function: {
|
||
name: t.function.name || t.function.function.name,
|
||
parameters: t.function.parameters,
|
||
description: t.function.description,
|
||
strict: t.function.strict
|
||
}
|
||
} : t) : void 0;
|
||
for (const message of params.messages) {
|
||
this._addMessage(message, false);
|
||
}
|
||
for (let i = 0; i < maxChatCompletions; ++i) {
|
||
const chatCompletion = await this._createChatCompletion(client, {
|
||
...restParams,
|
||
tool_choice,
|
||
tools,
|
||
messages: [...this.messages]
|
||
}, options);
|
||
const message = (_b = chatCompletion.choices[0]) == null ? void 0 : _b.message;
|
||
if (!message) {
|
||
throw new OpenAIError(`missing message in ChatCompletion response`);
|
||
}
|
||
if (!((_c = message.tool_calls) == null ? void 0 : _c.length)) {
|
||
return;
|
||
}
|
||
for (const tool_call of message.tool_calls) {
|
||
if (tool_call.type !== "function")
|
||
continue;
|
||
const tool_call_id = tool_call.id;
|
||
const { name, arguments: args } = tool_call.function;
|
||
const fn = functionsByName[name];
|
||
if (!fn) {
|
||
const content2 = `Invalid tool_call: ${JSON.stringify(name)}. Available options are: ${Object.keys(functionsByName).map((name2) => JSON.stringify(name2)).join(", ")}. Please try again`;
|
||
this._addMessage({ role, tool_call_id, content: content2 });
|
||
continue;
|
||
} else if (singleFunctionToCall && singleFunctionToCall !== name) {
|
||
const content2 = `Invalid tool_call: ${JSON.stringify(name)}. ${JSON.stringify(singleFunctionToCall)} requested. Please try again`;
|
||
this._addMessage({ role, tool_call_id, content: content2 });
|
||
continue;
|
||
}
|
||
let parsed;
|
||
try {
|
||
parsed = isRunnableFunctionWithParse(fn) ? await fn.parse(args) : args;
|
||
} catch (error) {
|
||
const content2 = error instanceof Error ? error.message : String(error);
|
||
this._addMessage({ role, tool_call_id, content: content2 });
|
||
continue;
|
||
}
|
||
const rawContent = await fn.function(parsed, this);
|
||
const content = __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_stringifyFunctionCallResult).call(this, rawContent);
|
||
this._addMessage({ role, tool_call_id, content });
|
||
if (singleFunctionToCall) {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
};
|
||
_AbstractChatCompletionRunner_instances = /* @__PURE__ */ new WeakSet(), _AbstractChatCompletionRunner_getFinalContent = function _AbstractChatCompletionRunner_getFinalContent2() {
|
||
var _a2;
|
||
return (_a2 = __classPrivateFieldGet3(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this).content) != null ? _a2 : null;
|
||
}, _AbstractChatCompletionRunner_getFinalMessage = function _AbstractChatCompletionRunner_getFinalMessage2() {
|
||
var _a2, _b;
|
||
let i = this.messages.length;
|
||
while (i-- > 0) {
|
||
const message = this.messages[i];
|
||
if (isAssistantMessage(message)) {
|
||
const { function_call, ...rest } = message;
|
||
const ret = {
|
||
...rest,
|
||
content: (_a2 = message.content) != null ? _a2 : null,
|
||
refusal: (_b = message.refusal) != null ? _b : null
|
||
};
|
||
if (function_call) {
|
||
ret.function_call = function_call;
|
||
}
|
||
return ret;
|
||
}
|
||
}
|
||
throw new OpenAIError("stream ended without producing a ChatCompletionMessage with role=assistant");
|
||
}, _AbstractChatCompletionRunner_getFinalFunctionCall = function _AbstractChatCompletionRunner_getFinalFunctionCall2() {
|
||
var _a2, _b;
|
||
for (let i = this.messages.length - 1; i >= 0; i--) {
|
||
const message = this.messages[i];
|
||
if (isAssistantMessage(message) && (message == null ? void 0 : message.function_call)) {
|
||
return message.function_call;
|
||
}
|
||
if (isAssistantMessage(message) && ((_a2 = message == null ? void 0 : message.tool_calls) == null ? void 0 : _a2.length)) {
|
||
return (_b = message.tool_calls.at(-1)) == null ? void 0 : _b.function;
|
||
}
|
||
}
|
||
return;
|
||
}, _AbstractChatCompletionRunner_getFinalFunctionCallResult = function _AbstractChatCompletionRunner_getFinalFunctionCallResult2() {
|
||
for (let i = this.messages.length - 1; i >= 0; i--) {
|
||
const message = this.messages[i];
|
||
if (isFunctionMessage(message) && message.content != null) {
|
||
return message.content;
|
||
}
|
||
if (isToolMessage(message) && message.content != null && typeof message.content === "string" && this.messages.some((x) => {
|
||
var _a2;
|
||
return x.role === "assistant" && ((_a2 = x.tool_calls) == null ? void 0 : _a2.some((y) => y.type === "function" && y.id === message.tool_call_id));
|
||
})) {
|
||
return message.content;
|
||
}
|
||
}
|
||
return;
|
||
}, _AbstractChatCompletionRunner_calculateTotalUsage = function _AbstractChatCompletionRunner_calculateTotalUsage2() {
|
||
const total = {
|
||
completion_tokens: 0,
|
||
prompt_tokens: 0,
|
||
total_tokens: 0
|
||
};
|
||
for (const { usage } of this._chatCompletions) {
|
||
if (usage) {
|
||
total.completion_tokens += usage.completion_tokens;
|
||
total.prompt_tokens += usage.prompt_tokens;
|
||
total.total_tokens += usage.total_tokens;
|
||
}
|
||
}
|
||
return total;
|
||
}, _AbstractChatCompletionRunner_validateParams = function _AbstractChatCompletionRunner_validateParams2(params) {
|
||
if (params.n != null && params.n > 1) {
|
||
throw new OpenAIError("ChatCompletion convenience helpers only support n=1 at this time. To use n>1, please use chat.completions.create() directly.");
|
||
}
|
||
}, _AbstractChatCompletionRunner_stringifyFunctionCallResult = function _AbstractChatCompletionRunner_stringifyFunctionCallResult2(rawContent) {
|
||
return typeof rawContent === "string" ? rawContent : rawContent === void 0 ? "undefined" : JSON.stringify(rawContent);
|
||
};
|
||
|
||
// node_modules/openai/lib/ChatCompletionRunner.mjs
|
||
var ChatCompletionRunner = class _ChatCompletionRunner extends AbstractChatCompletionRunner {
|
||
/** @deprecated - please use `runTools` instead. */
|
||
static runFunctions(client, params, options) {
|
||
const runner = new _ChatCompletionRunner();
|
||
const opts = {
|
||
...options,
|
||
headers: { ...options == null ? void 0 : options.headers, "X-Stainless-Helper-Method": "runFunctions" }
|
||
};
|
||
runner._run(() => runner._runFunctions(client, params, opts));
|
||
return runner;
|
||
}
|
||
static runTools(client, params, options) {
|
||
const runner = new _ChatCompletionRunner();
|
||
const opts = {
|
||
...options,
|
||
headers: { ...options == null ? void 0 : options.headers, "X-Stainless-Helper-Method": "runTools" }
|
||
};
|
||
runner._run(() => runner._runTools(client, params, opts));
|
||
return runner;
|
||
}
|
||
_addMessage(message, emit = true) {
|
||
super._addMessage(message, emit);
|
||
if (isAssistantMessage(message) && message.content) {
|
||
this._emit("content", message.content);
|
||
}
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/_vendor/partial-json-parser/parser.mjs
|
||
var STR = 1;
|
||
var NUM = 2;
|
||
var ARR = 4;
|
||
var OBJ = 8;
|
||
var NULL = 16;
|
||
var BOOL = 32;
|
||
var NAN = 64;
|
||
var INFINITY = 128;
|
||
var MINUS_INFINITY = 256;
|
||
var INF = INFINITY | MINUS_INFINITY;
|
||
var SPECIAL = NULL | BOOL | INF | NAN;
|
||
var ATOM = STR | NUM | SPECIAL;
|
||
var COLLECTION = ARR | OBJ;
|
||
var ALL = ATOM | COLLECTION;
|
||
var Allow = {
|
||
STR,
|
||
NUM,
|
||
ARR,
|
||
OBJ,
|
||
NULL,
|
||
BOOL,
|
||
NAN,
|
||
INFINITY,
|
||
MINUS_INFINITY,
|
||
INF,
|
||
SPECIAL,
|
||
ATOM,
|
||
COLLECTION,
|
||
ALL
|
||
};
|
||
var PartialJSON = class extends Error {
|
||
};
|
||
var MalformedJSON = class extends Error {
|
||
};
|
||
function parseJSON(jsonString, allowPartial = Allow.ALL) {
|
||
if (typeof jsonString !== "string") {
|
||
throw new TypeError(`expecting str, got ${typeof jsonString}`);
|
||
}
|
||
if (!jsonString.trim()) {
|
||
throw new Error(`${jsonString} is empty`);
|
||
}
|
||
return _parseJSON(jsonString.trim(), allowPartial);
|
||
}
|
||
var _parseJSON = (jsonString, allow) => {
|
||
const length = jsonString.length;
|
||
let index = 0;
|
||
const markPartialJSON = (msg) => {
|
||
throw new PartialJSON(`${msg} at position ${index}`);
|
||
};
|
||
const throwMalformedError = (msg) => {
|
||
throw new MalformedJSON(`${msg} at position ${index}`);
|
||
};
|
||
const parseAny = () => {
|
||
skipBlank();
|
||
if (index >= length)
|
||
markPartialJSON("Unexpected end of input");
|
||
if (jsonString[index] === '"')
|
||
return parseStr();
|
||
if (jsonString[index] === "{")
|
||
return parseObj();
|
||
if (jsonString[index] === "[")
|
||
return parseArr();
|
||
if (jsonString.substring(index, index + 4) === "null" || Allow.NULL & allow && length - index < 4 && "null".startsWith(jsonString.substring(index))) {
|
||
index += 4;
|
||
return null;
|
||
}
|
||
if (jsonString.substring(index, index + 4) === "true" || Allow.BOOL & allow && length - index < 4 && "true".startsWith(jsonString.substring(index))) {
|
||
index += 4;
|
||
return true;
|
||
}
|
||
if (jsonString.substring(index, index + 5) === "false" || Allow.BOOL & allow && length - index < 5 && "false".startsWith(jsonString.substring(index))) {
|
||
index += 5;
|
||
return false;
|
||
}
|
||
if (jsonString.substring(index, index + 8) === "Infinity" || Allow.INFINITY & allow && length - index < 8 && "Infinity".startsWith(jsonString.substring(index))) {
|
||
index += 8;
|
||
return Infinity;
|
||
}
|
||
if (jsonString.substring(index, index + 9) === "-Infinity" || Allow.MINUS_INFINITY & allow && 1 < length - index && length - index < 9 && "-Infinity".startsWith(jsonString.substring(index))) {
|
||
index += 9;
|
||
return -Infinity;
|
||
}
|
||
if (jsonString.substring(index, index + 3) === "NaN" || Allow.NAN & allow && length - index < 3 && "NaN".startsWith(jsonString.substring(index))) {
|
||
index += 3;
|
||
return NaN;
|
||
}
|
||
return parseNum();
|
||
};
|
||
const parseStr = () => {
|
||
const start = index;
|
||
let escape2 = false;
|
||
index++;
|
||
while (index < length && (jsonString[index] !== '"' || escape2 && jsonString[index - 1] === "\\")) {
|
||
escape2 = jsonString[index] === "\\" ? !escape2 : false;
|
||
index++;
|
||
}
|
||
if (jsonString.charAt(index) == '"') {
|
||
try {
|
||
return JSON.parse(jsonString.substring(start, ++index - Number(escape2)));
|
||
} catch (e) {
|
||
throwMalformedError(String(e));
|
||
}
|
||
} else if (Allow.STR & allow) {
|
||
try {
|
||
return JSON.parse(jsonString.substring(start, index - Number(escape2)) + '"');
|
||
} catch (e) {
|
||
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("\\")) + '"');
|
||
}
|
||
}
|
||
markPartialJSON("Unterminated string literal");
|
||
};
|
||
const parseObj = () => {
|
||
index++;
|
||
skipBlank();
|
||
const obj = {};
|
||
try {
|
||
while (jsonString[index] !== "}") {
|
||
skipBlank();
|
||
if (index >= length && Allow.OBJ & allow)
|
||
return obj;
|
||
const key = parseStr();
|
||
skipBlank();
|
||
index++;
|
||
try {
|
||
const value = parseAny();
|
||
Object.defineProperty(obj, key, { value, writable: true, enumerable: true, configurable: true });
|
||
} catch (e) {
|
||
if (Allow.OBJ & allow)
|
||
return obj;
|
||
else
|
||
throw e;
|
||
}
|
||
skipBlank();
|
||
if (jsonString[index] === ",")
|
||
index++;
|
||
}
|
||
} catch (e) {
|
||
if (Allow.OBJ & allow)
|
||
return obj;
|
||
else
|
||
markPartialJSON("Expected '}' at end of object");
|
||
}
|
||
index++;
|
||
return obj;
|
||
};
|
||
const parseArr = () => {
|
||
index++;
|
||
const arr = [];
|
||
try {
|
||
while (jsonString[index] !== "]") {
|
||
arr.push(parseAny());
|
||
skipBlank();
|
||
if (jsonString[index] === ",") {
|
||
index++;
|
||
}
|
||
}
|
||
} catch (e) {
|
||
if (Allow.ARR & allow) {
|
||
return arr;
|
||
}
|
||
markPartialJSON("Expected ']' at end of array");
|
||
}
|
||
index++;
|
||
return arr;
|
||
};
|
||
const parseNum = () => {
|
||
if (index === 0) {
|
||
if (jsonString === "-" && Allow.NUM & allow)
|
||
markPartialJSON("Not sure what '-' is");
|
||
try {
|
||
return JSON.parse(jsonString);
|
||
} catch (e) {
|
||
if (Allow.NUM & allow) {
|
||
try {
|
||
if ("." === jsonString[jsonString.length - 1])
|
||
return JSON.parse(jsonString.substring(0, jsonString.lastIndexOf(".")));
|
||
return JSON.parse(jsonString.substring(0, jsonString.lastIndexOf("e")));
|
||
} catch (e2) {
|
||
}
|
||
}
|
||
throwMalformedError(String(e));
|
||
}
|
||
}
|
||
const start = index;
|
||
if (jsonString[index] === "-")
|
||
index++;
|
||
while (jsonString[index] && !",]}".includes(jsonString[index]))
|
||
index++;
|
||
if (index == length && !(Allow.NUM & allow))
|
||
markPartialJSON("Unterminated number literal");
|
||
try {
|
||
return JSON.parse(jsonString.substring(start, index));
|
||
} catch (e) {
|
||
if (jsonString.substring(start, index) === "-" && Allow.NUM & allow)
|
||
markPartialJSON("Not sure what '-' is");
|
||
try {
|
||
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("e")));
|
||
} catch (e2) {
|
||
throwMalformedError(String(e2));
|
||
}
|
||
}
|
||
};
|
||
const skipBlank = () => {
|
||
while (index < length && " \n\r ".includes(jsonString[index])) {
|
||
index++;
|
||
}
|
||
};
|
||
return parseAny();
|
||
};
|
||
var partialParse = (input) => parseJSON(input, Allow.ALL ^ Allow.NUM);
|
||
|
||
// node_modules/openai/lib/ChatCompletionStream.mjs
|
||
var __classPrivateFieldSet3 = function(receiver, state, value, kind2, f) {
|
||
if (kind2 === "m")
|
||
throw new TypeError("Private method is not writable");
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a setter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
||
return kind2 === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
|
||
};
|
||
var __classPrivateFieldGet4 = function(receiver, state, kind2, f) {
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a getter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||
return kind2 === "m" ? f : kind2 === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||
};
|
||
var _ChatCompletionStream_instances;
|
||
var _ChatCompletionStream_params;
|
||
var _ChatCompletionStream_choiceEventStates;
|
||
var _ChatCompletionStream_currentChatCompletionSnapshot;
|
||
var _ChatCompletionStream_beginRequest;
|
||
var _ChatCompletionStream_getChoiceEventState;
|
||
var _ChatCompletionStream_addChunk;
|
||
var _ChatCompletionStream_emitToolCallDoneEvent;
|
||
var _ChatCompletionStream_emitContentDoneEvents;
|
||
var _ChatCompletionStream_endRequest;
|
||
var _ChatCompletionStream_getAutoParseableResponseFormat;
|
||
var _ChatCompletionStream_accumulateChatCompletion;
|
||
var ChatCompletionStream = class _ChatCompletionStream extends AbstractChatCompletionRunner {
|
||
constructor(params) {
|
||
super();
|
||
_ChatCompletionStream_instances.add(this);
|
||
_ChatCompletionStream_params.set(this, void 0);
|
||
_ChatCompletionStream_choiceEventStates.set(this, void 0);
|
||
_ChatCompletionStream_currentChatCompletionSnapshot.set(this, void 0);
|
||
__classPrivateFieldSet3(this, _ChatCompletionStream_params, params, "f");
|
||
__classPrivateFieldSet3(this, _ChatCompletionStream_choiceEventStates, [], "f");
|
||
}
|
||
get currentChatCompletionSnapshot() {
|
||
return __classPrivateFieldGet4(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
|
||
}
|
||
/**
|
||
* Intended for use on the frontend, consuming a stream produced with
|
||
* `.toReadableStream()` on the backend.
|
||
*
|
||
* Note that messages sent to the model do not appear in `.on('message')`
|
||
* in this context.
|
||
*/
|
||
static fromReadableStream(stream) {
|
||
const runner = new _ChatCompletionStream(null);
|
||
runner._run(() => runner._fromReadableStream(stream));
|
||
return runner;
|
||
}
|
||
static createChatCompletion(client, params, options) {
|
||
const runner = new _ChatCompletionStream(params);
|
||
runner._run(() => runner._runChatCompletion(client, { ...params, stream: true }, { ...options, headers: { ...options == null ? void 0 : options.headers, "X-Stainless-Helper-Method": "stream" } }));
|
||
return runner;
|
||
}
|
||
async _createChatCompletion(client, params, options) {
|
||
var _a2;
|
||
super._createChatCompletion;
|
||
const signal = options == null ? void 0 : options.signal;
|
||
if (signal) {
|
||
if (signal.aborted)
|
||
this.controller.abort();
|
||
signal.addEventListener("abort", () => this.controller.abort());
|
||
}
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_beginRequest).call(this);
|
||
const stream = await client.chat.completions.create({ ...params, stream: true }, { ...options, signal: this.controller.signal });
|
||
this._connected();
|
||
for await (const chunk of stream) {
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_addChunk).call(this, chunk);
|
||
}
|
||
if ((_a2 = stream.controller.signal) == null ? void 0 : _a2.aborted) {
|
||
throw new APIUserAbortError();
|
||
}
|
||
return this._addChatCompletion(__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
|
||
}
|
||
async _fromReadableStream(readableStream, options) {
|
||
var _a2;
|
||
const signal = options == null ? void 0 : options.signal;
|
||
if (signal) {
|
||
if (signal.aborted)
|
||
this.controller.abort();
|
||
signal.addEventListener("abort", () => this.controller.abort());
|
||
}
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_beginRequest).call(this);
|
||
this._connected();
|
||
const stream = Stream.fromReadableStream(readableStream, this.controller);
|
||
let chatId;
|
||
for await (const chunk of stream) {
|
||
if (chatId && chatId !== chunk.id) {
|
||
this._addChatCompletion(__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
|
||
}
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_addChunk).call(this, chunk);
|
||
chatId = chunk.id;
|
||
}
|
||
if ((_a2 = stream.controller.signal) == null ? void 0 : _a2.aborted) {
|
||
throw new APIUserAbortError();
|
||
}
|
||
return this._addChatCompletion(__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
|
||
}
|
||
[(_ChatCompletionStream_params = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_choiceEventStates = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_currentChatCompletionSnapshot = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_instances = /* @__PURE__ */ new WeakSet(), _ChatCompletionStream_beginRequest = function _ChatCompletionStream_beginRequest2() {
|
||
if (this.ended)
|
||
return;
|
||
__classPrivateFieldSet3(this, _ChatCompletionStream_currentChatCompletionSnapshot, void 0, "f");
|
||
}, _ChatCompletionStream_getChoiceEventState = function _ChatCompletionStream_getChoiceEventState2(choice) {
|
||
let state = __classPrivateFieldGet4(this, _ChatCompletionStream_choiceEventStates, "f")[choice.index];
|
||
if (state) {
|
||
return state;
|
||
}
|
||
state = {
|
||
content_done: false,
|
||
refusal_done: false,
|
||
logprobs_content_done: false,
|
||
logprobs_refusal_done: false,
|
||
done_tool_calls: /* @__PURE__ */ new Set(),
|
||
current_tool_call_index: null
|
||
};
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_choiceEventStates, "f")[choice.index] = state;
|
||
return state;
|
||
}, _ChatCompletionStream_addChunk = function _ChatCompletionStream_addChunk2(chunk) {
|
||
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
|
||
if (this.ended)
|
||
return;
|
||
const completion = __classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_accumulateChatCompletion).call(this, chunk);
|
||
this._emit("chunk", chunk, completion);
|
||
for (const choice of chunk.choices) {
|
||
const choiceSnapshot = completion.choices[choice.index];
|
||
if (choice.delta.content != null && ((_a2 = choiceSnapshot.message) == null ? void 0 : _a2.role) === "assistant" && ((_b = choiceSnapshot.message) == null ? void 0 : _b.content)) {
|
||
this._emit("content", choice.delta.content, choiceSnapshot.message.content);
|
||
this._emit("content.delta", {
|
||
delta: choice.delta.content,
|
||
snapshot: choiceSnapshot.message.content,
|
||
parsed: choiceSnapshot.message.parsed
|
||
});
|
||
}
|
||
if (choice.delta.refusal != null && ((_c = choiceSnapshot.message) == null ? void 0 : _c.role) === "assistant" && ((_d = choiceSnapshot.message) == null ? void 0 : _d.refusal)) {
|
||
this._emit("refusal.delta", {
|
||
delta: choice.delta.refusal,
|
||
snapshot: choiceSnapshot.message.refusal
|
||
});
|
||
}
|
||
if (((_e = choice.logprobs) == null ? void 0 : _e.content) != null && ((_f = choiceSnapshot.message) == null ? void 0 : _f.role) === "assistant") {
|
||
this._emit("logprobs.content.delta", {
|
||
content: (_g = choice.logprobs) == null ? void 0 : _g.content,
|
||
snapshot: (_i = (_h = choiceSnapshot.logprobs) == null ? void 0 : _h.content) != null ? _i : []
|
||
});
|
||
}
|
||
if (((_j = choice.logprobs) == null ? void 0 : _j.refusal) != null && ((_k = choiceSnapshot.message) == null ? void 0 : _k.role) === "assistant") {
|
||
this._emit("logprobs.refusal.delta", {
|
||
refusal: (_l = choice.logprobs) == null ? void 0 : _l.refusal,
|
||
snapshot: (_n = (_m = choiceSnapshot.logprobs) == null ? void 0 : _m.refusal) != null ? _n : []
|
||
});
|
||
}
|
||
const state = __classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
|
||
if (choiceSnapshot.finish_reason) {
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitContentDoneEvents).call(this, choiceSnapshot);
|
||
if (state.current_tool_call_index != null) {
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitToolCallDoneEvent).call(this, choiceSnapshot, state.current_tool_call_index);
|
||
}
|
||
}
|
||
for (const toolCall of (_o = choice.delta.tool_calls) != null ? _o : []) {
|
||
if (state.current_tool_call_index !== toolCall.index) {
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitContentDoneEvents).call(this, choiceSnapshot);
|
||
if (state.current_tool_call_index != null) {
|
||
__classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitToolCallDoneEvent).call(this, choiceSnapshot, state.current_tool_call_index);
|
||
}
|
||
}
|
||
state.current_tool_call_index = toolCall.index;
|
||
}
|
||
for (const toolCallDelta of (_p = choice.delta.tool_calls) != null ? _p : []) {
|
||
const toolCallSnapshot = (_q = choiceSnapshot.message.tool_calls) == null ? void 0 : _q[toolCallDelta.index];
|
||
if (!(toolCallSnapshot == null ? void 0 : toolCallSnapshot.type)) {
|
||
continue;
|
||
}
|
||
if ((toolCallSnapshot == null ? void 0 : toolCallSnapshot.type) === "function") {
|
||
this._emit("tool_calls.function.arguments.delta", {
|
||
name: (_r = toolCallSnapshot.function) == null ? void 0 : _r.name,
|
||
index: toolCallDelta.index,
|
||
arguments: toolCallSnapshot.function.arguments,
|
||
parsed_arguments: toolCallSnapshot.function.parsed_arguments,
|
||
arguments_delta: (_t = (_s = toolCallDelta.function) == null ? void 0 : _s.arguments) != null ? _t : ""
|
||
});
|
||
} else {
|
||
assertNever(toolCallSnapshot == null ? void 0 : toolCallSnapshot.type);
|
||
}
|
||
}
|
||
}
|
||
}, _ChatCompletionStream_emitToolCallDoneEvent = function _ChatCompletionStream_emitToolCallDoneEvent2(choiceSnapshot, toolCallIndex) {
|
||
var _a2, _b, _c;
|
||
const state = __classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
|
||
if (state.done_tool_calls.has(toolCallIndex)) {
|
||
return;
|
||
}
|
||
const toolCallSnapshot = (_a2 = choiceSnapshot.message.tool_calls) == null ? void 0 : _a2[toolCallIndex];
|
||
if (!toolCallSnapshot) {
|
||
throw new Error("no tool call snapshot");
|
||
}
|
||
if (!toolCallSnapshot.type) {
|
||
throw new Error("tool call snapshot missing `type`");
|
||
}
|
||
if (toolCallSnapshot.type === "function") {
|
||
const inputTool = (_c = (_b = __classPrivateFieldGet4(this, _ChatCompletionStream_params, "f")) == null ? void 0 : _b.tools) == null ? void 0 : _c.find((tool) => tool.type === "function" && tool.function.name === toolCallSnapshot.function.name);
|
||
this._emit("tool_calls.function.arguments.done", {
|
||
name: toolCallSnapshot.function.name,
|
||
index: toolCallIndex,
|
||
arguments: toolCallSnapshot.function.arguments,
|
||
parsed_arguments: isAutoParsableTool(inputTool) ? inputTool.$parseRaw(toolCallSnapshot.function.arguments) : (inputTool == null ? void 0 : inputTool.function.strict) ? JSON.parse(toolCallSnapshot.function.arguments) : null
|
||
});
|
||
} else {
|
||
assertNever(toolCallSnapshot.type);
|
||
}
|
||
}, _ChatCompletionStream_emitContentDoneEvents = function _ChatCompletionStream_emitContentDoneEvents2(choiceSnapshot) {
|
||
var _a2, _b;
|
||
const state = __classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
|
||
if (choiceSnapshot.message.content && !state.content_done) {
|
||
state.content_done = true;
|
||
const responseFormat = __classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getAutoParseableResponseFormat).call(this);
|
||
this._emit("content.done", {
|
||
content: choiceSnapshot.message.content,
|
||
parsed: responseFormat ? responseFormat.$parseRaw(choiceSnapshot.message.content) : null
|
||
});
|
||
}
|
||
if (choiceSnapshot.message.refusal && !state.refusal_done) {
|
||
state.refusal_done = true;
|
||
this._emit("refusal.done", { refusal: choiceSnapshot.message.refusal });
|
||
}
|
||
if (((_a2 = choiceSnapshot.logprobs) == null ? void 0 : _a2.content) && !state.logprobs_content_done) {
|
||
state.logprobs_content_done = true;
|
||
this._emit("logprobs.content.done", { content: choiceSnapshot.logprobs.content });
|
||
}
|
||
if (((_b = choiceSnapshot.logprobs) == null ? void 0 : _b.refusal) && !state.logprobs_refusal_done) {
|
||
state.logprobs_refusal_done = true;
|
||
this._emit("logprobs.refusal.done", { refusal: choiceSnapshot.logprobs.refusal });
|
||
}
|
||
}, _ChatCompletionStream_endRequest = function _ChatCompletionStream_endRequest2() {
|
||
if (this.ended) {
|
||
throw new OpenAIError(`stream has ended, this shouldn't happen`);
|
||
}
|
||
const snapshot = __classPrivateFieldGet4(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
|
||
if (!snapshot) {
|
||
throw new OpenAIError(`request ended without sending any chunks`);
|
||
}
|
||
__classPrivateFieldSet3(this, _ChatCompletionStream_currentChatCompletionSnapshot, void 0, "f");
|
||
__classPrivateFieldSet3(this, _ChatCompletionStream_choiceEventStates, [], "f");
|
||
return finalizeChatCompletion(snapshot, __classPrivateFieldGet4(this, _ChatCompletionStream_params, "f"));
|
||
}, _ChatCompletionStream_getAutoParseableResponseFormat = function _ChatCompletionStream_getAutoParseableResponseFormat2() {
|
||
var _a2;
|
||
const responseFormat = (_a2 = __classPrivateFieldGet4(this, _ChatCompletionStream_params, "f")) == null ? void 0 : _a2.response_format;
|
||
if (isAutoParsableResponseFormat(responseFormat)) {
|
||
return responseFormat;
|
||
}
|
||
return null;
|
||
}, _ChatCompletionStream_accumulateChatCompletion = function _ChatCompletionStream_accumulateChatCompletion2(chunk) {
|
||
var _a3, _b2, _c2, _d2, _e, _f;
|
||
var _a2, _b, _c, _d;
|
||
let snapshot = __classPrivateFieldGet4(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
|
||
const { choices, ...rest } = chunk;
|
||
if (!snapshot) {
|
||
snapshot = __classPrivateFieldSet3(this, _ChatCompletionStream_currentChatCompletionSnapshot, {
|
||
...rest,
|
||
choices: []
|
||
}, "f");
|
||
} else {
|
||
Object.assign(snapshot, rest);
|
||
}
|
||
for (const { delta, finish_reason, index, logprobs = null, ...other } of chunk.choices) {
|
||
let choice = snapshot.choices[index];
|
||
if (!choice) {
|
||
choice = snapshot.choices[index] = { finish_reason, index, message: {}, logprobs, ...other };
|
||
}
|
||
if (logprobs) {
|
||
if (!choice.logprobs) {
|
||
choice.logprobs = Object.assign({}, logprobs);
|
||
} else {
|
||
const { content: content2, refusal: refusal2, ...rest3 } = logprobs;
|
||
assertIsEmpty(rest3);
|
||
Object.assign(choice.logprobs, rest3);
|
||
if (content2) {
|
||
(_a3 = (_a2 = choice.logprobs).content) != null ? _a3 : _a2.content = [];
|
||
choice.logprobs.content.push(...content2);
|
||
}
|
||
if (refusal2) {
|
||
(_b2 = (_b = choice.logprobs).refusal) != null ? _b2 : _b.refusal = [];
|
||
choice.logprobs.refusal.push(...refusal2);
|
||
}
|
||
}
|
||
}
|
||
if (finish_reason) {
|
||
choice.finish_reason = finish_reason;
|
||
if (__classPrivateFieldGet4(this, _ChatCompletionStream_params, "f") && hasAutoParseableInput(__classPrivateFieldGet4(this, _ChatCompletionStream_params, "f"))) {
|
||
if (finish_reason === "length") {
|
||
throw new LengthFinishReasonError();
|
||
}
|
||
if (finish_reason === "content_filter") {
|
||
throw new ContentFilterFinishReasonError();
|
||
}
|
||
}
|
||
}
|
||
Object.assign(choice, other);
|
||
if (!delta)
|
||
continue;
|
||
const { content, refusal, function_call, role, tool_calls, ...rest2 } = delta;
|
||
assertIsEmpty(rest2);
|
||
Object.assign(choice.message, rest2);
|
||
if (refusal) {
|
||
choice.message.refusal = (choice.message.refusal || "") + refusal;
|
||
}
|
||
if (role)
|
||
choice.message.role = role;
|
||
if (function_call) {
|
||
if (!choice.message.function_call) {
|
||
choice.message.function_call = function_call;
|
||
} else {
|
||
if (function_call.name)
|
||
choice.message.function_call.name = function_call.name;
|
||
if (function_call.arguments) {
|
||
(_c2 = (_c = choice.message.function_call).arguments) != null ? _c2 : _c.arguments = "";
|
||
choice.message.function_call.arguments += function_call.arguments;
|
||
}
|
||
}
|
||
}
|
||
if (content) {
|
||
choice.message.content = (choice.message.content || "") + content;
|
||
if (!choice.message.refusal && __classPrivateFieldGet4(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getAutoParseableResponseFormat).call(this)) {
|
||
choice.message.parsed = partialParse(choice.message.content);
|
||
}
|
||
}
|
||
if (tool_calls) {
|
||
if (!choice.message.tool_calls)
|
||
choice.message.tool_calls = [];
|
||
for (const { index: index2, id, type, function: fn, ...rest3 } of tool_calls) {
|
||
const tool_call = (_d2 = (_d = choice.message.tool_calls)[index2]) != null ? _d2 : _d[index2] = {};
|
||
Object.assign(tool_call, rest3);
|
||
if (id)
|
||
tool_call.id = id;
|
||
if (type)
|
||
tool_call.type = type;
|
||
if (fn)
|
||
(_f = tool_call.function) != null ? _f : tool_call.function = { name: (_e = fn.name) != null ? _e : "", arguments: "" };
|
||
if (fn == null ? void 0 : fn.name)
|
||
tool_call.function.name = fn.name;
|
||
if (fn == null ? void 0 : fn.arguments) {
|
||
tool_call.function.arguments += fn.arguments;
|
||
if (shouldParseToolCall(__classPrivateFieldGet4(this, _ChatCompletionStream_params, "f"), tool_call)) {
|
||
tool_call.function.parsed_arguments = partialParse(tool_call.function.arguments);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return snapshot;
|
||
}, Symbol.asyncIterator)]() {
|
||
const pushQueue = [];
|
||
const readQueue = [];
|
||
let done = false;
|
||
this.on("chunk", (chunk) => {
|
||
const reader = readQueue.shift();
|
||
if (reader) {
|
||
reader.resolve(chunk);
|
||
} else {
|
||
pushQueue.push(chunk);
|
||
}
|
||
});
|
||
this.on("end", () => {
|
||
done = true;
|
||
for (const reader of readQueue) {
|
||
reader.resolve(void 0);
|
||
}
|
||
readQueue.length = 0;
|
||
});
|
||
this.on("abort", (err) => {
|
||
done = true;
|
||
for (const reader of readQueue) {
|
||
reader.reject(err);
|
||
}
|
||
readQueue.length = 0;
|
||
});
|
||
this.on("error", (err) => {
|
||
done = true;
|
||
for (const reader of readQueue) {
|
||
reader.reject(err);
|
||
}
|
||
readQueue.length = 0;
|
||
});
|
||
return {
|
||
next: async () => {
|
||
if (!pushQueue.length) {
|
||
if (done) {
|
||
return { value: void 0, done: true };
|
||
}
|
||
return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
||
}
|
||
const chunk = pushQueue.shift();
|
||
return { value: chunk, done: false };
|
||
},
|
||
return: async () => {
|
||
this.abort();
|
||
return { value: void 0, done: true };
|
||
}
|
||
};
|
||
}
|
||
toReadableStream() {
|
||
const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
|
||
return stream.toReadableStream();
|
||
}
|
||
};
|
||
function finalizeChatCompletion(snapshot, params) {
|
||
const { id, choices, created, model, system_fingerprint, ...rest } = snapshot;
|
||
const completion = {
|
||
...rest,
|
||
id,
|
||
choices: choices.map(({ message, finish_reason, index, logprobs, ...choiceRest }) => {
|
||
var _a2, _b, _c;
|
||
if (!finish_reason) {
|
||
throw new OpenAIError(`missing finish_reason for choice ${index}`);
|
||
}
|
||
const { content = null, function_call, tool_calls, ...messageRest } = message;
|
||
const role = message.role;
|
||
if (!role) {
|
||
throw new OpenAIError(`missing role for choice ${index}`);
|
||
}
|
||
if (function_call) {
|
||
const { arguments: args, name } = function_call;
|
||
if (args == null) {
|
||
throw new OpenAIError(`missing function_call.arguments for choice ${index}`);
|
||
}
|
||
if (!name) {
|
||
throw new OpenAIError(`missing function_call.name for choice ${index}`);
|
||
}
|
||
return {
|
||
...choiceRest,
|
||
message: {
|
||
content,
|
||
function_call: { arguments: args, name },
|
||
role,
|
||
refusal: (_a2 = message.refusal) != null ? _a2 : null
|
||
},
|
||
finish_reason,
|
||
index,
|
||
logprobs
|
||
};
|
||
}
|
||
if (tool_calls) {
|
||
return {
|
||
...choiceRest,
|
||
index,
|
||
finish_reason,
|
||
logprobs,
|
||
message: {
|
||
...messageRest,
|
||
role,
|
||
content,
|
||
refusal: (_b = message.refusal) != null ? _b : null,
|
||
tool_calls: tool_calls.map((tool_call, i) => {
|
||
const { function: fn, type, id: id2, ...toolRest } = tool_call;
|
||
const { arguments: args, name, ...fnRest } = fn || {};
|
||
if (id2 == null) {
|
||
throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].id
|
||
${str(snapshot)}`);
|
||
}
|
||
if (type == null) {
|
||
throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].type
|
||
${str(snapshot)}`);
|
||
}
|
||
if (name == null) {
|
||
throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].function.name
|
||
${str(snapshot)}`);
|
||
}
|
||
if (args == null) {
|
||
throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].function.arguments
|
||
${str(snapshot)}`);
|
||
}
|
||
return { ...toolRest, id: id2, type, function: { ...fnRest, name, arguments: args } };
|
||
})
|
||
}
|
||
};
|
||
}
|
||
return {
|
||
...choiceRest,
|
||
message: { ...messageRest, content, role, refusal: (_c = message.refusal) != null ? _c : null },
|
||
finish_reason,
|
||
index,
|
||
logprobs
|
||
};
|
||
}),
|
||
created,
|
||
model,
|
||
object: "chat.completion",
|
||
...system_fingerprint ? { system_fingerprint } : {}
|
||
};
|
||
return maybeParseChatCompletion(completion, params);
|
||
}
|
||
function str(x) {
|
||
return JSON.stringify(x);
|
||
}
|
||
function assertIsEmpty(obj) {
|
||
return;
|
||
}
|
||
function assertNever(_x) {
|
||
}
|
||
|
||
// node_modules/openai/lib/ChatCompletionStreamingRunner.mjs
|
||
var ChatCompletionStreamingRunner = class _ChatCompletionStreamingRunner extends ChatCompletionStream {
|
||
static fromReadableStream(stream) {
|
||
const runner = new _ChatCompletionStreamingRunner(null);
|
||
runner._run(() => runner._fromReadableStream(stream));
|
||
return runner;
|
||
}
|
||
/** @deprecated - please use `runTools` instead. */
|
||
static runFunctions(client, params, options) {
|
||
const runner = new _ChatCompletionStreamingRunner(null);
|
||
const opts = {
|
||
...options,
|
||
headers: { ...options == null ? void 0 : options.headers, "X-Stainless-Helper-Method": "runFunctions" }
|
||
};
|
||
runner._run(() => runner._runFunctions(client, params, opts));
|
||
return runner;
|
||
}
|
||
static runTools(client, params, options) {
|
||
const runner = new _ChatCompletionStreamingRunner(
|
||
// @ts-expect-error TODO these types are incompatible
|
||
params
|
||
);
|
||
const opts = {
|
||
...options,
|
||
headers: { ...options == null ? void 0 : options.headers, "X-Stainless-Helper-Method": "runTools" }
|
||
};
|
||
runner._run(() => runner._runTools(client, params, opts));
|
||
return runner;
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/beta/chat/completions.mjs
|
||
var Completions2 = class extends APIResource {
|
||
parse(body, options) {
|
||
validateInputTools(body.tools);
|
||
return this._client.chat.completions.create(body, {
|
||
...options,
|
||
headers: {
|
||
...options == null ? void 0 : options.headers,
|
||
"X-Stainless-Helper-Method": "beta.chat.completions.parse"
|
||
}
|
||
})._thenUnwrap((completion) => parseChatCompletion(completion, body));
|
||
}
|
||
runFunctions(body, options) {
|
||
if (body.stream) {
|
||
return ChatCompletionStreamingRunner.runFunctions(this._client, body, options);
|
||
}
|
||
return ChatCompletionRunner.runFunctions(this._client, body, options);
|
||
}
|
||
runTools(body, options) {
|
||
if (body.stream) {
|
||
return ChatCompletionStreamingRunner.runTools(this._client, body, options);
|
||
}
|
||
return ChatCompletionRunner.runTools(this._client, body, options);
|
||
}
|
||
/**
|
||
* Creates a chat completion stream
|
||
*/
|
||
stream(body, options) {
|
||
return ChatCompletionStream.createChatCompletion(this._client, body, options);
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/beta/chat/chat.mjs
|
||
var Chat2 = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.completions = new Completions2(this._client);
|
||
}
|
||
};
|
||
(function(Chat3) {
|
||
Chat3.Completions = Completions2;
|
||
})(Chat2 || (Chat2 = {}));
|
||
|
||
// node_modules/openai/lib/AssistantStream.mjs
|
||
var __classPrivateFieldGet5 = function(receiver, state, kind2, f) {
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a getter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||
return kind2 === "m" ? f : kind2 === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||
};
|
||
var __classPrivateFieldSet4 = function(receiver, state, value, kind2, f) {
|
||
if (kind2 === "m")
|
||
throw new TypeError("Private method is not writable");
|
||
if (kind2 === "a" && !f)
|
||
throw new TypeError("Private accessor was defined without a setter");
|
||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||
throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
||
return kind2 === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
|
||
};
|
||
var _AssistantStream_instances;
|
||
var _AssistantStream_events;
|
||
var _AssistantStream_runStepSnapshots;
|
||
var _AssistantStream_messageSnapshots;
|
||
var _AssistantStream_messageSnapshot;
|
||
var _AssistantStream_finalRun;
|
||
var _AssistantStream_currentContentIndex;
|
||
var _AssistantStream_currentContent;
|
||
var _AssistantStream_currentToolCallIndex;
|
||
var _AssistantStream_currentToolCall;
|
||
var _AssistantStream_currentEvent;
|
||
var _AssistantStream_currentRunSnapshot;
|
||
var _AssistantStream_currentRunStepSnapshot;
|
||
var _AssistantStream_addEvent;
|
||
var _AssistantStream_endRequest;
|
||
var _AssistantStream_handleMessage;
|
||
var _AssistantStream_handleRunStep;
|
||
var _AssistantStream_handleEvent;
|
||
var _AssistantStream_accumulateRunStep;
|
||
var _AssistantStream_accumulateMessage;
|
||
var _AssistantStream_accumulateContent;
|
||
var _AssistantStream_handleRun;
|
||
var AssistantStream = class _AssistantStream extends EventStream {
|
||
constructor() {
|
||
super(...arguments);
|
||
_AssistantStream_instances.add(this);
|
||
_AssistantStream_events.set(this, []);
|
||
_AssistantStream_runStepSnapshots.set(this, {});
|
||
_AssistantStream_messageSnapshots.set(this, {});
|
||
_AssistantStream_messageSnapshot.set(this, void 0);
|
||
_AssistantStream_finalRun.set(this, void 0);
|
||
_AssistantStream_currentContentIndex.set(this, void 0);
|
||
_AssistantStream_currentContent.set(this, void 0);
|
||
_AssistantStream_currentToolCallIndex.set(this, void 0);
|
||
_AssistantStream_currentToolCall.set(this, void 0);
|
||
_AssistantStream_currentEvent.set(this, void 0);
|
||
_AssistantStream_currentRunSnapshot.set(this, void 0);
|
||
_AssistantStream_currentRunStepSnapshot.set(this, void 0);
|
||
}
|
||
[(_AssistantStream_events = /* @__PURE__ */ new WeakMap(), _AssistantStream_runStepSnapshots = /* @__PURE__ */ new WeakMap(), _AssistantStream_messageSnapshots = /* @__PURE__ */ new WeakMap(), _AssistantStream_messageSnapshot = /* @__PURE__ */ new WeakMap(), _AssistantStream_finalRun = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentContentIndex = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentContent = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentToolCallIndex = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentToolCall = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentEvent = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentRunSnapshot = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentRunStepSnapshot = /* @__PURE__ */ new WeakMap(), _AssistantStream_instances = /* @__PURE__ */ new WeakSet(), Symbol.asyncIterator)]() {
|
||
const pushQueue = [];
|
||
const readQueue = [];
|
||
let done = false;
|
||
this.on("event", (event) => {
|
||
const reader = readQueue.shift();
|
||
if (reader) {
|
||
reader.resolve(event);
|
||
} else {
|
||
pushQueue.push(event);
|
||
}
|
||
});
|
||
this.on("end", () => {
|
||
done = true;
|
||
for (const reader of readQueue) {
|
||
reader.resolve(void 0);
|
||
}
|
||
readQueue.length = 0;
|
||
});
|
||
this.on("abort", (err) => {
|
||
done = true;
|
||
for (const reader of readQueue) {
|
||
reader.reject(err);
|
||
}
|
||
readQueue.length = 0;
|
||
});
|
||
this.on("error", (err) => {
|
||
done = true;
|
||
for (const reader of readQueue) {
|
||
reader.reject(err);
|
||
}
|
||
readQueue.length = 0;
|
||
});
|
||
return {
|
||
next: async () => {
|
||
if (!pushQueue.length) {
|
||
if (done) {
|
||
return { value: void 0, done: true };
|
||
}
|
||
return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
||
}
|
||
const chunk = pushQueue.shift();
|
||
return { value: chunk, done: false };
|
||
},
|
||
return: async () => {
|
||
this.abort();
|
||
return { value: void 0, done: true };
|
||
}
|
||
};
|
||
}
|
||
static fromReadableStream(stream) {
|
||
const runner = new _AssistantStream();
|
||
runner._run(() => runner._fromReadableStream(stream));
|
||
return runner;
|
||
}
|
||
async _fromReadableStream(readableStream, options) {
|
||
var _a2;
|
||
const signal = options == null ? void 0 : options.signal;
|
||
if (signal) {
|
||
if (signal.aborted)
|
||
this.controller.abort();
|
||
signal.addEventListener("abort", () => this.controller.abort());
|
||
}
|
||
this._connected();
|
||
const stream = Stream.fromReadableStream(readableStream, this.controller);
|
||
for await (const event of stream) {
|
||
__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event);
|
||
}
|
||
if ((_a2 = stream.controller.signal) == null ? void 0 : _a2.aborted) {
|
||
throw new APIUserAbortError();
|
||
}
|
||
return this._addRun(__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
|
||
}
|
||
toReadableStream() {
|
||
const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
|
||
return stream.toReadableStream();
|
||
}
|
||
static createToolAssistantStream(threadId, runId, runs, params, options) {
|
||
const runner = new _AssistantStream();
|
||
runner._run(() => runner._runToolAssistantStream(threadId, runId, runs, params, {
|
||
...options,
|
||
headers: { ...options == null ? void 0 : options.headers, "X-Stainless-Helper-Method": "stream" }
|
||
}));
|
||
return runner;
|
||
}
|
||
async _createToolAssistantStream(run, threadId, runId, params, options) {
|
||
var _a2;
|
||
const signal = options == null ? void 0 : options.signal;
|
||
if (signal) {
|
||
if (signal.aborted)
|
||
this.controller.abort();
|
||
signal.addEventListener("abort", () => this.controller.abort());
|
||
}
|
||
const body = { ...params, stream: true };
|
||
const stream = await run.submitToolOutputs(threadId, runId, body, {
|
||
...options,
|
||
signal: this.controller.signal
|
||
});
|
||
this._connected();
|
||
for await (const event of stream) {
|
||
__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event);
|
||
}
|
||
if ((_a2 = stream.controller.signal) == null ? void 0 : _a2.aborted) {
|
||
throw new APIUserAbortError();
|
||
}
|
||
return this._addRun(__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
|
||
}
|
||
static createThreadAssistantStream(params, thread, options) {
|
||
const runner = new _AssistantStream();
|
||
runner._run(() => runner._threadAssistantStream(params, thread, {
|
||
...options,
|
||
headers: { ...options == null ? void 0 : options.headers, "X-Stainless-Helper-Method": "stream" }
|
||
}));
|
||
return runner;
|
||
}
|
||
static createAssistantStream(threadId, runs, params, options) {
|
||
const runner = new _AssistantStream();
|
||
runner._run(() => runner._runAssistantStream(threadId, runs, params, {
|
||
...options,
|
||
headers: { ...options == null ? void 0 : options.headers, "X-Stainless-Helper-Method": "stream" }
|
||
}));
|
||
return runner;
|
||
}
|
||
currentEvent() {
|
||
return __classPrivateFieldGet5(this, _AssistantStream_currentEvent, "f");
|
||
}
|
||
currentRun() {
|
||
return __classPrivateFieldGet5(this, _AssistantStream_currentRunSnapshot, "f");
|
||
}
|
||
currentMessageSnapshot() {
|
||
return __classPrivateFieldGet5(this, _AssistantStream_messageSnapshot, "f");
|
||
}
|
||
currentRunStepSnapshot() {
|
||
return __classPrivateFieldGet5(this, _AssistantStream_currentRunStepSnapshot, "f");
|
||
}
|
||
async finalRunSteps() {
|
||
await this.done();
|
||
return Object.values(__classPrivateFieldGet5(this, _AssistantStream_runStepSnapshots, "f"));
|
||
}
|
||
async finalMessages() {
|
||
await this.done();
|
||
return Object.values(__classPrivateFieldGet5(this, _AssistantStream_messageSnapshots, "f"));
|
||
}
|
||
async finalRun() {
|
||
await this.done();
|
||
if (!__classPrivateFieldGet5(this, _AssistantStream_finalRun, "f"))
|
||
throw Error("Final run was not received.");
|
||
return __classPrivateFieldGet5(this, _AssistantStream_finalRun, "f");
|
||
}
|
||
async _createThreadAssistantStream(thread, params, options) {
|
||
var _a2;
|
||
const signal = options == null ? void 0 : options.signal;
|
||
if (signal) {
|
||
if (signal.aborted)
|
||
this.controller.abort();
|
||
signal.addEventListener("abort", () => this.controller.abort());
|
||
}
|
||
const body = { ...params, stream: true };
|
||
const stream = await thread.createAndRun(body, { ...options, signal: this.controller.signal });
|
||
this._connected();
|
||
for await (const event of stream) {
|
||
__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event);
|
||
}
|
||
if ((_a2 = stream.controller.signal) == null ? void 0 : _a2.aborted) {
|
||
throw new APIUserAbortError();
|
||
}
|
||
return this._addRun(__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
|
||
}
|
||
async _createAssistantStream(run, threadId, params, options) {
|
||
var _a2;
|
||
const signal = options == null ? void 0 : options.signal;
|
||
if (signal) {
|
||
if (signal.aborted)
|
||
this.controller.abort();
|
||
signal.addEventListener("abort", () => this.controller.abort());
|
||
}
|
||
const body = { ...params, stream: true };
|
||
const stream = await run.create(threadId, body, { ...options, signal: this.controller.signal });
|
||
this._connected();
|
||
for await (const event of stream) {
|
||
__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event);
|
||
}
|
||
if ((_a2 = stream.controller.signal) == null ? void 0 : _a2.aborted) {
|
||
throw new APIUserAbortError();
|
||
}
|
||
return this._addRun(__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
|
||
}
|
||
static accumulateDelta(acc, delta) {
|
||
for (const [key, deltaValue] of Object.entries(delta)) {
|
||
if (!acc.hasOwnProperty(key)) {
|
||
acc[key] = deltaValue;
|
||
continue;
|
||
}
|
||
let accValue = acc[key];
|
||
if (accValue === null || accValue === void 0) {
|
||
acc[key] = deltaValue;
|
||
continue;
|
||
}
|
||
if (key === "index" || key === "type") {
|
||
acc[key] = deltaValue;
|
||
continue;
|
||
}
|
||
if (typeof accValue === "string" && typeof deltaValue === "string") {
|
||
accValue += deltaValue;
|
||
} else if (typeof accValue === "number" && typeof deltaValue === "number") {
|
||
accValue += deltaValue;
|
||
} else if (isObj(accValue) && isObj(deltaValue)) {
|
||
accValue = this.accumulateDelta(accValue, deltaValue);
|
||
} else if (Array.isArray(accValue) && Array.isArray(deltaValue)) {
|
||
if (accValue.every((x) => typeof x === "string" || typeof x === "number")) {
|
||
accValue.push(...deltaValue);
|
||
continue;
|
||
}
|
||
for (const deltaEntry of deltaValue) {
|
||
if (!isObj(deltaEntry)) {
|
||
throw new Error(`Expected array delta entry to be an object but got: ${deltaEntry}`);
|
||
}
|
||
const index = deltaEntry["index"];
|
||
if (index == null) {
|
||
console.error(deltaEntry);
|
||
throw new Error("Expected array delta entry to have an `index` property");
|
||
}
|
||
if (typeof index !== "number") {
|
||
throw new Error(`Expected array delta entry \`index\` property to be a number but got ${index}`);
|
||
}
|
||
const accEntry = accValue[index];
|
||
if (accEntry == null) {
|
||
accValue.push(deltaEntry);
|
||
} else {
|
||
accValue[index] = this.accumulateDelta(accEntry, deltaEntry);
|
||
}
|
||
}
|
||
continue;
|
||
} else {
|
||
throw Error(`Unhandled record type: ${key}, deltaValue: ${deltaValue}, accValue: ${accValue}`);
|
||
}
|
||
acc[key] = accValue;
|
||
}
|
||
return acc;
|
||
}
|
||
_addRun(run) {
|
||
return run;
|
||
}
|
||
async _threadAssistantStream(params, thread, options) {
|
||
return await this._createThreadAssistantStream(thread, params, options);
|
||
}
|
||
async _runAssistantStream(threadId, runs, params, options) {
|
||
return await this._createAssistantStream(runs, threadId, params, options);
|
||
}
|
||
async _runToolAssistantStream(threadId, runId, runs, params, options) {
|
||
return await this._createToolAssistantStream(runs, threadId, runId, params, options);
|
||
}
|
||
};
|
||
_AssistantStream_addEvent = function _AssistantStream_addEvent2(event) {
|
||
if (this.ended)
|
||
return;
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentEvent, event, "f");
|
||
__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_handleEvent).call(this, event);
|
||
switch (event.event) {
|
||
case "thread.created":
|
||
break;
|
||
case "thread.run.created":
|
||
case "thread.run.queued":
|
||
case "thread.run.in_progress":
|
||
case "thread.run.requires_action":
|
||
case "thread.run.completed":
|
||
case "thread.run.failed":
|
||
case "thread.run.cancelling":
|
||
case "thread.run.cancelled":
|
||
case "thread.run.expired":
|
||
__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_handleRun).call(this, event);
|
||
break;
|
||
case "thread.run.step.created":
|
||
case "thread.run.step.in_progress":
|
||
case "thread.run.step.delta":
|
||
case "thread.run.step.completed":
|
||
case "thread.run.step.failed":
|
||
case "thread.run.step.cancelled":
|
||
case "thread.run.step.expired":
|
||
__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_handleRunStep).call(this, event);
|
||
break;
|
||
case "thread.message.created":
|
||
case "thread.message.in_progress":
|
||
case "thread.message.delta":
|
||
case "thread.message.completed":
|
||
case "thread.message.incomplete":
|
||
__classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_handleMessage).call(this, event);
|
||
break;
|
||
case "error":
|
||
throw new Error("Encountered an error event in event processing - errors should be processed earlier");
|
||
}
|
||
}, _AssistantStream_endRequest = function _AssistantStream_endRequest2() {
|
||
if (this.ended) {
|
||
throw new OpenAIError(`stream has ended, this shouldn't happen`);
|
||
}
|
||
if (!__classPrivateFieldGet5(this, _AssistantStream_finalRun, "f"))
|
||
throw Error("Final run has not been received");
|
||
return __classPrivateFieldGet5(this, _AssistantStream_finalRun, "f");
|
||
}, _AssistantStream_handleMessage = function _AssistantStream_handleMessage2(event) {
|
||
const [accumulatedMessage, newContent] = __classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_accumulateMessage).call(this, event, __classPrivateFieldGet5(this, _AssistantStream_messageSnapshot, "f"));
|
||
__classPrivateFieldSet4(this, _AssistantStream_messageSnapshot, accumulatedMessage, "f");
|
||
__classPrivateFieldGet5(this, _AssistantStream_messageSnapshots, "f")[accumulatedMessage.id] = accumulatedMessage;
|
||
for (const content of newContent) {
|
||
const snapshotContent = accumulatedMessage.content[content.index];
|
||
if ((snapshotContent == null ? void 0 : snapshotContent.type) == "text") {
|
||
this._emit("textCreated", snapshotContent.text);
|
||
}
|
||
}
|
||
switch (event.event) {
|
||
case "thread.message.created":
|
||
this._emit("messageCreated", event.data);
|
||
break;
|
||
case "thread.message.in_progress":
|
||
break;
|
||
case "thread.message.delta":
|
||
this._emit("messageDelta", event.data.delta, accumulatedMessage);
|
||
if (event.data.delta.content) {
|
||
for (const content of event.data.delta.content) {
|
||
if (content.type == "text" && content.text) {
|
||
let textDelta = content.text;
|
||
let snapshot = accumulatedMessage.content[content.index];
|
||
if (snapshot && snapshot.type == "text") {
|
||
this._emit("textDelta", textDelta, snapshot.text);
|
||
} else {
|
||
throw Error("The snapshot associated with this text delta is not text or missing");
|
||
}
|
||
}
|
||
if (content.index != __classPrivateFieldGet5(this, _AssistantStream_currentContentIndex, "f")) {
|
||
if (__classPrivateFieldGet5(this, _AssistantStream_currentContent, "f")) {
|
||
switch (__classPrivateFieldGet5(this, _AssistantStream_currentContent, "f").type) {
|
||
case "text":
|
||
this._emit("textDone", __classPrivateFieldGet5(this, _AssistantStream_currentContent, "f").text, __classPrivateFieldGet5(this, _AssistantStream_messageSnapshot, "f"));
|
||
break;
|
||
case "image_file":
|
||
this._emit("imageFileDone", __classPrivateFieldGet5(this, _AssistantStream_currentContent, "f").image_file, __classPrivateFieldGet5(this, _AssistantStream_messageSnapshot, "f"));
|
||
break;
|
||
}
|
||
}
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentContentIndex, content.index, "f");
|
||
}
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentContent, accumulatedMessage.content[content.index], "f");
|
||
}
|
||
}
|
||
break;
|
||
case "thread.message.completed":
|
||
case "thread.message.incomplete":
|
||
if (__classPrivateFieldGet5(this, _AssistantStream_currentContentIndex, "f") !== void 0) {
|
||
const currentContent = event.data.content[__classPrivateFieldGet5(this, _AssistantStream_currentContentIndex, "f")];
|
||
if (currentContent) {
|
||
switch (currentContent.type) {
|
||
case "image_file":
|
||
this._emit("imageFileDone", currentContent.image_file, __classPrivateFieldGet5(this, _AssistantStream_messageSnapshot, "f"));
|
||
break;
|
||
case "text":
|
||
this._emit("textDone", currentContent.text, __classPrivateFieldGet5(this, _AssistantStream_messageSnapshot, "f"));
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (__classPrivateFieldGet5(this, _AssistantStream_messageSnapshot, "f")) {
|
||
this._emit("messageDone", event.data);
|
||
}
|
||
__classPrivateFieldSet4(this, _AssistantStream_messageSnapshot, void 0, "f");
|
||
}
|
||
}, _AssistantStream_handleRunStep = function _AssistantStream_handleRunStep2(event) {
|
||
const accumulatedRunStep = __classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_accumulateRunStep).call(this, event);
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentRunStepSnapshot, accumulatedRunStep, "f");
|
||
switch (event.event) {
|
||
case "thread.run.step.created":
|
||
this._emit("runStepCreated", event.data);
|
||
break;
|
||
case "thread.run.step.delta":
|
||
const delta = event.data.delta;
|
||
if (delta.step_details && delta.step_details.type == "tool_calls" && delta.step_details.tool_calls && accumulatedRunStep.step_details.type == "tool_calls") {
|
||
for (const toolCall of delta.step_details.tool_calls) {
|
||
if (toolCall.index == __classPrivateFieldGet5(this, _AssistantStream_currentToolCallIndex, "f")) {
|
||
this._emit("toolCallDelta", toolCall, accumulatedRunStep.step_details.tool_calls[toolCall.index]);
|
||
} else {
|
||
if (__classPrivateFieldGet5(this, _AssistantStream_currentToolCall, "f")) {
|
||
this._emit("toolCallDone", __classPrivateFieldGet5(this, _AssistantStream_currentToolCall, "f"));
|
||
}
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentToolCallIndex, toolCall.index, "f");
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentToolCall, accumulatedRunStep.step_details.tool_calls[toolCall.index], "f");
|
||
if (__classPrivateFieldGet5(this, _AssistantStream_currentToolCall, "f"))
|
||
this._emit("toolCallCreated", __classPrivateFieldGet5(this, _AssistantStream_currentToolCall, "f"));
|
||
}
|
||
}
|
||
}
|
||
this._emit("runStepDelta", event.data.delta, accumulatedRunStep);
|
||
break;
|
||
case "thread.run.step.completed":
|
||
case "thread.run.step.failed":
|
||
case "thread.run.step.cancelled":
|
||
case "thread.run.step.expired":
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentRunStepSnapshot, void 0, "f");
|
||
const details = event.data.step_details;
|
||
if (details.type == "tool_calls") {
|
||
if (__classPrivateFieldGet5(this, _AssistantStream_currentToolCall, "f")) {
|
||
this._emit("toolCallDone", __classPrivateFieldGet5(this, _AssistantStream_currentToolCall, "f"));
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentToolCall, void 0, "f");
|
||
}
|
||
}
|
||
this._emit("runStepDone", event.data, accumulatedRunStep);
|
||
break;
|
||
case "thread.run.step.in_progress":
|
||
break;
|
||
}
|
||
}, _AssistantStream_handleEvent = function _AssistantStream_handleEvent2(event) {
|
||
__classPrivateFieldGet5(this, _AssistantStream_events, "f").push(event);
|
||
this._emit("event", event);
|
||
}, _AssistantStream_accumulateRunStep = function _AssistantStream_accumulateRunStep2(event) {
|
||
switch (event.event) {
|
||
case "thread.run.step.created":
|
||
__classPrivateFieldGet5(this, _AssistantStream_runStepSnapshots, "f")[event.data.id] = event.data;
|
||
return event.data;
|
||
case "thread.run.step.delta":
|
||
let snapshot = __classPrivateFieldGet5(this, _AssistantStream_runStepSnapshots, "f")[event.data.id];
|
||
if (!snapshot) {
|
||
throw Error("Received a RunStepDelta before creation of a snapshot");
|
||
}
|
||
let data = event.data;
|
||
if (data.delta) {
|
||
const accumulated = AssistantStream.accumulateDelta(snapshot, data.delta);
|
||
__classPrivateFieldGet5(this, _AssistantStream_runStepSnapshots, "f")[event.data.id] = accumulated;
|
||
}
|
||
return __classPrivateFieldGet5(this, _AssistantStream_runStepSnapshots, "f")[event.data.id];
|
||
case "thread.run.step.completed":
|
||
case "thread.run.step.failed":
|
||
case "thread.run.step.cancelled":
|
||
case "thread.run.step.expired":
|
||
case "thread.run.step.in_progress":
|
||
__classPrivateFieldGet5(this, _AssistantStream_runStepSnapshots, "f")[event.data.id] = event.data;
|
||
break;
|
||
}
|
||
if (__classPrivateFieldGet5(this, _AssistantStream_runStepSnapshots, "f")[event.data.id])
|
||
return __classPrivateFieldGet5(this, _AssistantStream_runStepSnapshots, "f")[event.data.id];
|
||
throw new Error("No snapshot available");
|
||
}, _AssistantStream_accumulateMessage = function _AssistantStream_accumulateMessage2(event, snapshot) {
|
||
let newContent = [];
|
||
switch (event.event) {
|
||
case "thread.message.created":
|
||
return [event.data, newContent];
|
||
case "thread.message.delta":
|
||
if (!snapshot) {
|
||
throw Error("Received a delta with no existing snapshot (there should be one from message creation)");
|
||
}
|
||
let data = event.data;
|
||
if (data.delta.content) {
|
||
for (const contentElement of data.delta.content) {
|
||
if (contentElement.index in snapshot.content) {
|
||
let currentContent = snapshot.content[contentElement.index];
|
||
snapshot.content[contentElement.index] = __classPrivateFieldGet5(this, _AssistantStream_instances, "m", _AssistantStream_accumulateContent).call(this, contentElement, currentContent);
|
||
} else {
|
||
snapshot.content[contentElement.index] = contentElement;
|
||
newContent.push(contentElement);
|
||
}
|
||
}
|
||
}
|
||
return [snapshot, newContent];
|
||
case "thread.message.in_progress":
|
||
case "thread.message.completed":
|
||
case "thread.message.incomplete":
|
||
if (snapshot) {
|
||
return [snapshot, newContent];
|
||
} else {
|
||
throw Error("Received thread message event with no existing snapshot");
|
||
}
|
||
}
|
||
throw Error("Tried to accumulate a non-message event");
|
||
}, _AssistantStream_accumulateContent = function _AssistantStream_accumulateContent2(contentElement, currentContent) {
|
||
return AssistantStream.accumulateDelta(currentContent, contentElement);
|
||
}, _AssistantStream_handleRun = function _AssistantStream_handleRun2(event) {
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentRunSnapshot, event.data, "f");
|
||
switch (event.event) {
|
||
case "thread.run.created":
|
||
break;
|
||
case "thread.run.queued":
|
||
break;
|
||
case "thread.run.in_progress":
|
||
break;
|
||
case "thread.run.requires_action":
|
||
case "thread.run.cancelled":
|
||
case "thread.run.failed":
|
||
case "thread.run.completed":
|
||
case "thread.run.expired":
|
||
__classPrivateFieldSet4(this, _AssistantStream_finalRun, event.data, "f");
|
||
if (__classPrivateFieldGet5(this, _AssistantStream_currentToolCall, "f")) {
|
||
this._emit("toolCallDone", __classPrivateFieldGet5(this, _AssistantStream_currentToolCall, "f"));
|
||
__classPrivateFieldSet4(this, _AssistantStream_currentToolCall, void 0, "f");
|
||
}
|
||
break;
|
||
case "thread.run.cancelling":
|
||
break;
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/beta/threads/messages.mjs
|
||
var Messages = class extends APIResource {
|
||
/**
|
||
* Create a message.
|
||
*/
|
||
create(threadId, body, options) {
|
||
return this._client.post(`/threads/${threadId}/messages`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Retrieve a message.
|
||
*/
|
||
retrieve(threadId, messageId, options) {
|
||
return this._client.get(`/threads/${threadId}/messages/${messageId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Modifies a message.
|
||
*/
|
||
update(threadId, messageId, body, options) {
|
||
return this._client.post(`/threads/${threadId}/messages/${messageId}`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
list(threadId, query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list(threadId, {}, query);
|
||
}
|
||
return this._client.getAPIList(`/threads/${threadId}/messages`, MessagesPage, {
|
||
query,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Deletes a message.
|
||
*/
|
||
del(threadId, messageId, options) {
|
||
return this._client.delete(`/threads/${threadId}/messages/${messageId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
};
|
||
var MessagesPage = class extends CursorPage {
|
||
};
|
||
Messages.MessagesPage = MessagesPage;
|
||
|
||
// node_modules/openai/resources/beta/threads/runs/steps.mjs
|
||
var Steps = class extends APIResource {
|
||
retrieve(threadId, runId, stepId, query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.retrieve(threadId, runId, stepId, {}, query);
|
||
}
|
||
return this._client.get(`/threads/${threadId}/runs/${runId}/steps/${stepId}`, {
|
||
query,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
list(threadId, runId, query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list(threadId, runId, {}, query);
|
||
}
|
||
return this._client.getAPIList(`/threads/${threadId}/runs/${runId}/steps`, RunStepsPage, {
|
||
query,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
};
|
||
var RunStepsPage = class extends CursorPage {
|
||
};
|
||
Steps.RunStepsPage = RunStepsPage;
|
||
|
||
// node_modules/openai/resources/beta/threads/runs/runs.mjs
|
||
var Runs = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.steps = new Steps(this._client);
|
||
}
|
||
create(threadId, params, options) {
|
||
var _a2;
|
||
const { include, ...body } = params;
|
||
return this._client.post(`/threads/${threadId}/runs`, {
|
||
query: { include },
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers },
|
||
stream: (_a2 = params.stream) != null ? _a2 : false
|
||
});
|
||
}
|
||
/**
|
||
* Retrieves a run.
|
||
*/
|
||
retrieve(threadId, runId, options) {
|
||
return this._client.get(`/threads/${threadId}/runs/${runId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Modifies a run.
|
||
*/
|
||
update(threadId, runId, body, options) {
|
||
return this._client.post(`/threads/${threadId}/runs/${runId}`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
list(threadId, query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list(threadId, {}, query);
|
||
}
|
||
return this._client.getAPIList(`/threads/${threadId}/runs`, RunsPage, {
|
||
query,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Cancels a run that is `in_progress`.
|
||
*/
|
||
cancel(threadId, runId, options) {
|
||
return this._client.post(`/threads/${threadId}/runs/${runId}/cancel`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* A helper to create a run an poll for a terminal state. More information on Run
|
||
* lifecycles can be found here:
|
||
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
|
||
*/
|
||
async createAndPoll(threadId, body, options) {
|
||
const run = await this.create(threadId, body, options);
|
||
return await this.poll(threadId, run.id, options);
|
||
}
|
||
/**
|
||
* Create a Run stream
|
||
*
|
||
* @deprecated use `stream` instead
|
||
*/
|
||
createAndStream(threadId, body, options) {
|
||
return AssistantStream.createAssistantStream(threadId, this._client.beta.threads.runs, body, options);
|
||
}
|
||
/**
|
||
* A helper to poll a run status until it reaches a terminal state. More
|
||
* information on Run lifecycles can be found here:
|
||
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
|
||
*/
|
||
async poll(threadId, runId, options) {
|
||
const headers = { ...options == null ? void 0 : options.headers, "X-Stainless-Poll-Helper": "true" };
|
||
if (options == null ? void 0 : options.pollIntervalMs) {
|
||
headers["X-Stainless-Custom-Poll-Interval"] = options.pollIntervalMs.toString();
|
||
}
|
||
while (true) {
|
||
const { data: run, response } = await this.retrieve(threadId, runId, {
|
||
...options,
|
||
headers: { ...options == null ? void 0 : options.headers, ...headers }
|
||
}).withResponse();
|
||
switch (run.status) {
|
||
case "queued":
|
||
case "in_progress":
|
||
case "cancelling":
|
||
let sleepInterval = 5e3;
|
||
if (options == null ? void 0 : options.pollIntervalMs) {
|
||
sleepInterval = options.pollIntervalMs;
|
||
} else {
|
||
const headerInterval = response.headers.get("openai-poll-after-ms");
|
||
if (headerInterval) {
|
||
const headerIntervalMs = parseInt(headerInterval);
|
||
if (!isNaN(headerIntervalMs)) {
|
||
sleepInterval = headerIntervalMs;
|
||
}
|
||
}
|
||
}
|
||
await sleep(sleepInterval);
|
||
break;
|
||
case "requires_action":
|
||
case "incomplete":
|
||
case "cancelled":
|
||
case "completed":
|
||
case "failed":
|
||
case "expired":
|
||
return run;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Create a Run stream
|
||
*/
|
||
stream(threadId, body, options) {
|
||
return AssistantStream.createAssistantStream(threadId, this._client.beta.threads.runs, body, options);
|
||
}
|
||
submitToolOutputs(threadId, runId, body, options) {
|
||
var _a2;
|
||
return this._client.post(`/threads/${threadId}/runs/${runId}/submit_tool_outputs`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers },
|
||
stream: (_a2 = body.stream) != null ? _a2 : false
|
||
});
|
||
}
|
||
/**
|
||
* A helper to submit a tool output to a run and poll for a terminal run state.
|
||
* More information on Run lifecycles can be found here:
|
||
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
|
||
*/
|
||
async submitToolOutputsAndPoll(threadId, runId, body, options) {
|
||
const run = await this.submitToolOutputs(threadId, runId, body, options);
|
||
return await this.poll(threadId, run.id, options);
|
||
}
|
||
/**
|
||
* Submit the tool outputs from a previous run and stream the run to a terminal
|
||
* state. More information on Run lifecycles can be found here:
|
||
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
|
||
*/
|
||
submitToolOutputsStream(threadId, runId, body, options) {
|
||
return AssistantStream.createToolAssistantStream(threadId, runId, this._client.beta.threads.runs, body, options);
|
||
}
|
||
};
|
||
var RunsPage = class extends CursorPage {
|
||
};
|
||
Runs.RunsPage = RunsPage;
|
||
Runs.Steps = Steps;
|
||
Runs.RunStepsPage = RunStepsPage;
|
||
|
||
// node_modules/openai/resources/beta/threads/threads.mjs
|
||
var Threads = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.runs = new Runs(this._client);
|
||
this.messages = new Messages(this._client);
|
||
}
|
||
create(body = {}, options) {
|
||
if (isRequestOptions(body)) {
|
||
return this.create({}, body);
|
||
}
|
||
return this._client.post("/threads", {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Retrieves a thread.
|
||
*/
|
||
retrieve(threadId, options) {
|
||
return this._client.get(`/threads/${threadId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Modifies a thread.
|
||
*/
|
||
update(threadId, body, options) {
|
||
return this._client.post(`/threads/${threadId}`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Delete a thread.
|
||
*/
|
||
del(threadId, options) {
|
||
return this._client.delete(`/threads/${threadId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
createAndRun(body, options) {
|
||
var _a2;
|
||
return this._client.post("/threads/runs", {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers },
|
||
stream: (_a2 = body.stream) != null ? _a2 : false
|
||
});
|
||
}
|
||
/**
|
||
* A helper to create a thread, start a run and then poll for a terminal state.
|
||
* More information on Run lifecycles can be found here:
|
||
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
|
||
*/
|
||
async createAndRunPoll(body, options) {
|
||
const run = await this.createAndRun(body, options);
|
||
return await this.runs.poll(run.thread_id, run.id, options);
|
||
}
|
||
/**
|
||
* Create a thread and stream the run back
|
||
*/
|
||
createAndRunStream(body, options) {
|
||
return AssistantStream.createThreadAssistantStream(body, this._client.beta.threads, options);
|
||
}
|
||
};
|
||
Threads.Runs = Runs;
|
||
Threads.RunsPage = RunsPage;
|
||
Threads.Messages = Messages;
|
||
Threads.MessagesPage = MessagesPage;
|
||
|
||
// node_modules/openai/lib/Util.mjs
|
||
var allSettledWithThrow = async (promises) => {
|
||
const results = await Promise.allSettled(promises);
|
||
const rejected = results.filter((result) => result.status === "rejected");
|
||
if (rejected.length) {
|
||
for (const result of rejected) {
|
||
console.error(result.reason);
|
||
}
|
||
throw new Error(`${rejected.length} promise(s) failed - see the above errors`);
|
||
}
|
||
const values = [];
|
||
for (const result of results) {
|
||
if (result.status === "fulfilled") {
|
||
values.push(result.value);
|
||
}
|
||
}
|
||
return values;
|
||
};
|
||
|
||
// node_modules/openai/resources/beta/vector-stores/files.mjs
|
||
var Files = class extends APIResource {
|
||
/**
|
||
* Create a vector store file by attaching a
|
||
* [File](https://platform.openai.com/docs/api-reference/files) to a
|
||
* [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object).
|
||
*/
|
||
create(vectorStoreId, body, options) {
|
||
return this._client.post(`/vector_stores/${vectorStoreId}/files`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Retrieves a vector store file.
|
||
*/
|
||
retrieve(vectorStoreId, fileId, options) {
|
||
return this._client.get(`/vector_stores/${vectorStoreId}/files/${fileId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
list(vectorStoreId, query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list(vectorStoreId, {}, query);
|
||
}
|
||
return this._client.getAPIList(`/vector_stores/${vectorStoreId}/files`, VectorStoreFilesPage, {
|
||
query,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Delete a vector store file. This will remove the file from the vector store but
|
||
* the file itself will not be deleted. To delete the file, use the
|
||
* [delete file](https://platform.openai.com/docs/api-reference/files/delete)
|
||
* endpoint.
|
||
*/
|
||
del(vectorStoreId, fileId, options) {
|
||
return this._client.delete(`/vector_stores/${vectorStoreId}/files/${fileId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Attach a file to the given vector store and wait for it to be processed.
|
||
*/
|
||
async createAndPoll(vectorStoreId, body, options) {
|
||
const file = await this.create(vectorStoreId, body, options);
|
||
return await this.poll(vectorStoreId, file.id, options);
|
||
}
|
||
/**
|
||
* Wait for the vector store file to finish processing.
|
||
*
|
||
* Note: this will return even if the file failed to process, you need to check
|
||
* file.last_error and file.status to handle these cases
|
||
*/
|
||
async poll(vectorStoreId, fileId, options) {
|
||
const headers = { ...options == null ? void 0 : options.headers, "X-Stainless-Poll-Helper": "true" };
|
||
if (options == null ? void 0 : options.pollIntervalMs) {
|
||
headers["X-Stainless-Custom-Poll-Interval"] = options.pollIntervalMs.toString();
|
||
}
|
||
while (true) {
|
||
const fileResponse = await this.retrieve(vectorStoreId, fileId, {
|
||
...options,
|
||
headers
|
||
}).withResponse();
|
||
const file = fileResponse.data;
|
||
switch (file.status) {
|
||
case "in_progress":
|
||
let sleepInterval = 5e3;
|
||
if (options == null ? void 0 : options.pollIntervalMs) {
|
||
sleepInterval = options.pollIntervalMs;
|
||
} else {
|
||
const headerInterval = fileResponse.response.headers.get("openai-poll-after-ms");
|
||
if (headerInterval) {
|
||
const headerIntervalMs = parseInt(headerInterval);
|
||
if (!isNaN(headerIntervalMs)) {
|
||
sleepInterval = headerIntervalMs;
|
||
}
|
||
}
|
||
}
|
||
await sleep(sleepInterval);
|
||
break;
|
||
case "failed":
|
||
case "completed":
|
||
return file;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Upload a file to the `files` API and then attach it to the given vector store.
|
||
*
|
||
* Note the file will be asynchronously processed (you can use the alternative
|
||
* polling helper method to wait for processing to complete).
|
||
*/
|
||
async upload(vectorStoreId, file, options) {
|
||
const fileInfo = await this._client.files.create({ file, purpose: "assistants" }, options);
|
||
return this.create(vectorStoreId, { file_id: fileInfo.id }, options);
|
||
}
|
||
/**
|
||
* Add a file to a vector store and poll until processing is complete.
|
||
*/
|
||
async uploadAndPoll(vectorStoreId, file, options) {
|
||
const fileInfo = await this.upload(vectorStoreId, file, options);
|
||
return await this.poll(vectorStoreId, fileInfo.id, options);
|
||
}
|
||
};
|
||
var VectorStoreFilesPage = class extends CursorPage {
|
||
};
|
||
Files.VectorStoreFilesPage = VectorStoreFilesPage;
|
||
|
||
// node_modules/openai/resources/beta/vector-stores/file-batches.mjs
|
||
var FileBatches = class extends APIResource {
|
||
/**
|
||
* Create a vector store file batch.
|
||
*/
|
||
create(vectorStoreId, body, options) {
|
||
return this._client.post(`/vector_stores/${vectorStoreId}/file_batches`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Retrieves a vector store file batch.
|
||
*/
|
||
retrieve(vectorStoreId, batchId, options) {
|
||
return this._client.get(`/vector_stores/${vectorStoreId}/file_batches/${batchId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Cancel a vector store file batch. This attempts to cancel the processing of
|
||
* files in this batch as soon as possible.
|
||
*/
|
||
cancel(vectorStoreId, batchId, options) {
|
||
return this._client.post(`/vector_stores/${vectorStoreId}/file_batches/${batchId}/cancel`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Create a vector store batch and poll until all files have been processed.
|
||
*/
|
||
async createAndPoll(vectorStoreId, body, options) {
|
||
const batch = await this.create(vectorStoreId, body);
|
||
return await this.poll(vectorStoreId, batch.id, options);
|
||
}
|
||
listFiles(vectorStoreId, batchId, query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.listFiles(vectorStoreId, batchId, {}, query);
|
||
}
|
||
return this._client.getAPIList(`/vector_stores/${vectorStoreId}/file_batches/${batchId}/files`, VectorStoreFilesPage, { query, ...options, headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers } });
|
||
}
|
||
/**
|
||
* Wait for the given file batch to be processed.
|
||
*
|
||
* Note: this will return even if one of the files failed to process, you need to
|
||
* check batch.file_counts.failed_count to handle this case.
|
||
*/
|
||
async poll(vectorStoreId, batchId, options) {
|
||
const headers = { ...options == null ? void 0 : options.headers, "X-Stainless-Poll-Helper": "true" };
|
||
if (options == null ? void 0 : options.pollIntervalMs) {
|
||
headers["X-Stainless-Custom-Poll-Interval"] = options.pollIntervalMs.toString();
|
||
}
|
||
while (true) {
|
||
const { data: batch, response } = await this.retrieve(vectorStoreId, batchId, {
|
||
...options,
|
||
headers
|
||
}).withResponse();
|
||
switch (batch.status) {
|
||
case "in_progress":
|
||
let sleepInterval = 5e3;
|
||
if (options == null ? void 0 : options.pollIntervalMs) {
|
||
sleepInterval = options.pollIntervalMs;
|
||
} else {
|
||
const headerInterval = response.headers.get("openai-poll-after-ms");
|
||
if (headerInterval) {
|
||
const headerIntervalMs = parseInt(headerInterval);
|
||
if (!isNaN(headerIntervalMs)) {
|
||
sleepInterval = headerIntervalMs;
|
||
}
|
||
}
|
||
}
|
||
await sleep(sleepInterval);
|
||
break;
|
||
case "failed":
|
||
case "cancelled":
|
||
case "completed":
|
||
return batch;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Uploads the given files concurrently and then creates a vector store file batch.
|
||
*
|
||
* The concurrency limit is configurable using the `maxConcurrency` parameter.
|
||
*/
|
||
async uploadAndPoll(vectorStoreId, { files, fileIds = [] }, options) {
|
||
var _a2;
|
||
if (files == null || files.length == 0) {
|
||
throw new Error(`No \`files\` provided to process. If you've already uploaded files you should use \`.createAndPoll()\` instead`);
|
||
}
|
||
const configuredConcurrency = (_a2 = options == null ? void 0 : options.maxConcurrency) != null ? _a2 : 5;
|
||
const concurrencyLimit = Math.min(configuredConcurrency, files.length);
|
||
const client = this._client;
|
||
const fileIterator = files.values();
|
||
const allFileIds = [...fileIds];
|
||
async function processFiles(iterator) {
|
||
for (let item of iterator) {
|
||
const fileObj = await client.files.create({ file: item, purpose: "assistants" }, options);
|
||
allFileIds.push(fileObj.id);
|
||
}
|
||
}
|
||
const workers = Array(concurrencyLimit).fill(fileIterator).map(processFiles);
|
||
await allSettledWithThrow(workers);
|
||
return await this.createAndPoll(vectorStoreId, {
|
||
file_ids: allFileIds
|
||
});
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/beta/vector-stores/vector-stores.mjs
|
||
var VectorStores = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.files = new Files(this._client);
|
||
this.fileBatches = new FileBatches(this._client);
|
||
}
|
||
/**
|
||
* Create a vector store.
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/vector_stores", {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Retrieves a vector store.
|
||
*/
|
||
retrieve(vectorStoreId, options) {
|
||
return this._client.get(`/vector_stores/${vectorStoreId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Modifies a vector store.
|
||
*/
|
||
update(vectorStoreId, body, options) {
|
||
return this._client.post(`/vector_stores/${vectorStoreId}`, {
|
||
body,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
list(query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list({}, query);
|
||
}
|
||
return this._client.getAPIList("/vector_stores", VectorStoresPage, {
|
||
query,
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Delete a vector store.
|
||
*/
|
||
del(vectorStoreId, options) {
|
||
return this._client.delete(`/vector_stores/${vectorStoreId}`, {
|
||
...options,
|
||
headers: { "OpenAI-Beta": "assistants=v2", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
};
|
||
var VectorStoresPage = class extends CursorPage {
|
||
};
|
||
VectorStores.VectorStoresPage = VectorStoresPage;
|
||
VectorStores.Files = Files;
|
||
VectorStores.VectorStoreFilesPage = VectorStoreFilesPage;
|
||
VectorStores.FileBatches = FileBatches;
|
||
|
||
// node_modules/openai/resources/beta/beta.mjs
|
||
var Beta = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.vectorStores = new VectorStores(this._client);
|
||
this.chat = new Chat2(this._client);
|
||
this.assistants = new Assistants(this._client);
|
||
this.threads = new Threads(this._client);
|
||
}
|
||
};
|
||
Beta.VectorStores = VectorStores;
|
||
Beta.VectorStoresPage = VectorStoresPage;
|
||
Beta.Assistants = Assistants;
|
||
Beta.AssistantsPage = AssistantsPage;
|
||
Beta.Threads = Threads;
|
||
|
||
// node_modules/openai/resources/completions.mjs
|
||
var Completions3 = class extends APIResource {
|
||
create(body, options) {
|
||
var _a2;
|
||
return this._client.post("/completions", { body, ...options, stream: (_a2 = body.stream) != null ? _a2 : false });
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/embeddings.mjs
|
||
var Embeddings = class extends APIResource {
|
||
/**
|
||
* Creates an embedding vector representing the input text.
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/embeddings", { body, ...options });
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/files.mjs
|
||
var Files2 = class extends APIResource {
|
||
/**
|
||
* Upload a file that can be used across various endpoints. Individual files can be
|
||
* up to 512 MB, and the size of all files uploaded by one organization can be up
|
||
* to 100 GB.
|
||
*
|
||
* The Assistants API supports files up to 2 million tokens and of specific file
|
||
* types. See the
|
||
* [Assistants Tools guide](https://platform.openai.com/docs/assistants/tools) for
|
||
* details.
|
||
*
|
||
* The Fine-tuning API only supports `.jsonl` files. The input also has certain
|
||
* required formats for fine-tuning
|
||
* [chat](https://platform.openai.com/docs/api-reference/fine-tuning/chat-input) or
|
||
* [completions](https://platform.openai.com/docs/api-reference/fine-tuning/completions-input)
|
||
* models.
|
||
*
|
||
* The Batch API only supports `.jsonl` files up to 200 MB in size. The input also
|
||
* has a specific required
|
||
* [format](https://platform.openai.com/docs/api-reference/batch/request-input).
|
||
*
|
||
* Please [contact us](https://help.openai.com/) if you need to increase these
|
||
* storage limits.
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/files", multipartFormRequestOptions({ body, ...options }));
|
||
}
|
||
/**
|
||
* Returns information about a specific file.
|
||
*/
|
||
retrieve(fileId, options) {
|
||
return this._client.get(`/files/${fileId}`, options);
|
||
}
|
||
list(query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list({}, query);
|
||
}
|
||
return this._client.getAPIList("/files", FileObjectsPage, { query, ...options });
|
||
}
|
||
/**
|
||
* Delete a file.
|
||
*/
|
||
del(fileId, options) {
|
||
return this._client.delete(`/files/${fileId}`, options);
|
||
}
|
||
/**
|
||
* Returns the contents of the specified file.
|
||
*/
|
||
content(fileId, options) {
|
||
return this._client.get(`/files/${fileId}/content`, { ...options, __binaryResponse: true });
|
||
}
|
||
/**
|
||
* Returns the contents of the specified file.
|
||
*
|
||
* @deprecated The `.content()` method should be used instead
|
||
*/
|
||
retrieveContent(fileId, options) {
|
||
return this._client.get(`/files/${fileId}/content`, {
|
||
...options,
|
||
headers: { Accept: "application/json", ...options == null ? void 0 : options.headers }
|
||
});
|
||
}
|
||
/**
|
||
* Waits for the given file to be processed, default timeout is 30 mins.
|
||
*/
|
||
async waitForProcessing(id, { pollInterval = 5e3, maxWait = 30 * 60 * 1e3 } = {}) {
|
||
const TERMINAL_STATES = /* @__PURE__ */ new Set(["processed", "error", "deleted"]);
|
||
const start = Date.now();
|
||
let file = await this.retrieve(id);
|
||
while (!file.status || !TERMINAL_STATES.has(file.status)) {
|
||
await sleep(pollInterval);
|
||
file = await this.retrieve(id);
|
||
if (Date.now() - start > maxWait) {
|
||
throw new APIConnectionTimeoutError({
|
||
message: `Giving up on waiting for file ${id} to finish processing after ${maxWait} milliseconds.`
|
||
});
|
||
}
|
||
}
|
||
return file;
|
||
}
|
||
};
|
||
var FileObjectsPage = class extends CursorPage {
|
||
};
|
||
Files2.FileObjectsPage = FileObjectsPage;
|
||
|
||
// node_modules/openai/resources/fine-tuning/jobs/checkpoints.mjs
|
||
var Checkpoints = class extends APIResource {
|
||
list(fineTuningJobId, query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list(fineTuningJobId, {}, query);
|
||
}
|
||
return this._client.getAPIList(`/fine_tuning/jobs/${fineTuningJobId}/checkpoints`, FineTuningJobCheckpointsPage, { query, ...options });
|
||
}
|
||
};
|
||
var FineTuningJobCheckpointsPage = class extends CursorPage {
|
||
};
|
||
Checkpoints.FineTuningJobCheckpointsPage = FineTuningJobCheckpointsPage;
|
||
|
||
// node_modules/openai/resources/fine-tuning/jobs/jobs.mjs
|
||
var Jobs = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.checkpoints = new Checkpoints(this._client);
|
||
}
|
||
/**
|
||
* Creates a fine-tuning job which begins the process of creating a new model from
|
||
* a given dataset.
|
||
*
|
||
* Response includes details of the enqueued job including job status and the name
|
||
* of the fine-tuned models once complete.
|
||
*
|
||
* [Learn more about fine-tuning](https://platform.openai.com/docs/guides/fine-tuning)
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/fine_tuning/jobs", { body, ...options });
|
||
}
|
||
/**
|
||
* Get info about a fine-tuning job.
|
||
*
|
||
* [Learn more about fine-tuning](https://platform.openai.com/docs/guides/fine-tuning)
|
||
*/
|
||
retrieve(fineTuningJobId, options) {
|
||
return this._client.get(`/fine_tuning/jobs/${fineTuningJobId}`, options);
|
||
}
|
||
list(query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.list({}, query);
|
||
}
|
||
return this._client.getAPIList("/fine_tuning/jobs", FineTuningJobsPage, { query, ...options });
|
||
}
|
||
/**
|
||
* Immediately cancel a fine-tune job.
|
||
*/
|
||
cancel(fineTuningJobId, options) {
|
||
return this._client.post(`/fine_tuning/jobs/${fineTuningJobId}/cancel`, options);
|
||
}
|
||
listEvents(fineTuningJobId, query = {}, options) {
|
||
if (isRequestOptions(query)) {
|
||
return this.listEvents(fineTuningJobId, {}, query);
|
||
}
|
||
return this._client.getAPIList(`/fine_tuning/jobs/${fineTuningJobId}/events`, FineTuningJobEventsPage, {
|
||
query,
|
||
...options
|
||
});
|
||
}
|
||
};
|
||
var FineTuningJobsPage = class extends CursorPage {
|
||
};
|
||
var FineTuningJobEventsPage = class extends CursorPage {
|
||
};
|
||
Jobs.FineTuningJobsPage = FineTuningJobsPage;
|
||
Jobs.FineTuningJobEventsPage = FineTuningJobEventsPage;
|
||
Jobs.Checkpoints = Checkpoints;
|
||
Jobs.FineTuningJobCheckpointsPage = FineTuningJobCheckpointsPage;
|
||
|
||
// node_modules/openai/resources/fine-tuning/fine-tuning.mjs
|
||
var FineTuning = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.jobs = new Jobs(this._client);
|
||
}
|
||
};
|
||
FineTuning.Jobs = Jobs;
|
||
FineTuning.FineTuningJobsPage = FineTuningJobsPage;
|
||
FineTuning.FineTuningJobEventsPage = FineTuningJobEventsPage;
|
||
|
||
// node_modules/openai/resources/images.mjs
|
||
var Images = class extends APIResource {
|
||
/**
|
||
* Creates a variation of a given image.
|
||
*/
|
||
createVariation(body, options) {
|
||
return this._client.post("/images/variations", multipartFormRequestOptions({ body, ...options }));
|
||
}
|
||
/**
|
||
* Creates an edited or extended image given an original image and a prompt.
|
||
*/
|
||
edit(body, options) {
|
||
return this._client.post("/images/edits", multipartFormRequestOptions({ body, ...options }));
|
||
}
|
||
/**
|
||
* Creates an image given a prompt.
|
||
*/
|
||
generate(body, options) {
|
||
return this._client.post("/images/generations", { body, ...options });
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/models.mjs
|
||
var Models = class extends APIResource {
|
||
/**
|
||
* Retrieves a model instance, providing basic information about the model such as
|
||
* the owner and permissioning.
|
||
*/
|
||
retrieve(model, options) {
|
||
return this._client.get(`/models/${model}`, options);
|
||
}
|
||
/**
|
||
* Lists the currently available models, and provides basic information about each
|
||
* one such as the owner and availability.
|
||
*/
|
||
list(options) {
|
||
return this._client.getAPIList("/models", ModelsPage, options);
|
||
}
|
||
/**
|
||
* Delete a fine-tuned model. You must have the Owner role in your organization to
|
||
* delete a model.
|
||
*/
|
||
del(model, options) {
|
||
return this._client.delete(`/models/${model}`, options);
|
||
}
|
||
};
|
||
var ModelsPage = class extends Page {
|
||
};
|
||
Models.ModelsPage = ModelsPage;
|
||
|
||
// node_modules/openai/resources/moderations.mjs
|
||
var Moderations = class extends APIResource {
|
||
/**
|
||
* Classifies if text and/or image inputs are potentially harmful. Learn more in
|
||
* the [moderation guide](https://platform.openai.com/docs/guides/moderation).
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/moderations", { body, ...options });
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/uploads/parts.mjs
|
||
var Parts = class extends APIResource {
|
||
/**
|
||
* Adds a
|
||
* [Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an
|
||
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object.
|
||
* A Part represents a chunk of bytes from the file you are trying to upload.
|
||
*
|
||
* Each Part can be at most 64 MB, and you can add Parts until you hit the Upload
|
||
* maximum of 8 GB.
|
||
*
|
||
* It is possible to add multiple Parts in parallel. You can decide the intended
|
||
* order of the Parts when you
|
||
* [complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete).
|
||
*/
|
||
create(uploadId, body, options) {
|
||
return this._client.post(`/uploads/${uploadId}/parts`, multipartFormRequestOptions({ body, ...options }));
|
||
}
|
||
};
|
||
|
||
// node_modules/openai/resources/uploads/uploads.mjs
|
||
var Uploads = class extends APIResource {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.parts = new Parts(this._client);
|
||
}
|
||
/**
|
||
* Creates an intermediate
|
||
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object
|
||
* that you can add
|
||
* [Parts](https://platform.openai.com/docs/api-reference/uploads/part-object) to.
|
||
* Currently, an Upload can accept at most 8 GB in total and expires after an hour
|
||
* after you create it.
|
||
*
|
||
* Once you complete the Upload, we will create a
|
||
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
|
||
* contains all the parts you uploaded. This File is usable in the rest of our
|
||
* platform as a regular File object.
|
||
*
|
||
* For certain `purpose`s, the correct `mime_type` must be specified. Please refer
|
||
* to documentation for the supported MIME types for your use case:
|
||
*
|
||
* - [Assistants](https://platform.openai.com/docs/assistants/tools/file-search#supported-files)
|
||
*
|
||
* For guidance on the proper filename extensions for each purpose, please follow
|
||
* the documentation on
|
||
* [creating a File](https://platform.openai.com/docs/api-reference/files/create).
|
||
*/
|
||
create(body, options) {
|
||
return this._client.post("/uploads", { body, ...options });
|
||
}
|
||
/**
|
||
* Cancels the Upload. No Parts may be added after an Upload is cancelled.
|
||
*/
|
||
cancel(uploadId, options) {
|
||
return this._client.post(`/uploads/${uploadId}/cancel`, options);
|
||
}
|
||
/**
|
||
* Completes the
|
||
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object).
|
||
*
|
||
* Within the returned Upload object, there is a nested
|
||
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
|
||
* is ready to use in the rest of the platform.
|
||
*
|
||
* You can specify the order of the Parts by passing in an ordered list of the Part
|
||
* IDs.
|
||
*
|
||
* The number of bytes uploaded upon completion must match the number of bytes
|
||
* initially specified when creating the Upload object. No Parts may be added after
|
||
* an Upload is completed.
|
||
*/
|
||
complete(uploadId, body, options) {
|
||
return this._client.post(`/uploads/${uploadId}/complete`, { body, ...options });
|
||
}
|
||
};
|
||
Uploads.Parts = Parts;
|
||
|
||
// node_modules/openai/index.mjs
|
||
var _a;
|
||
var OpenAI = class extends APIClient {
|
||
/**
|
||
* API Client for interfacing with the OpenAI API.
|
||
*
|
||
* @param {string | undefined} [opts.apiKey=process.env['OPENAI_API_KEY'] ?? undefined]
|
||
* @param {string | null | undefined} [opts.organization=process.env['OPENAI_ORG_ID'] ?? null]
|
||
* @param {string | null | undefined} [opts.project=process.env['OPENAI_PROJECT_ID'] ?? null]
|
||
* @param {string} [opts.baseURL=process.env['OPENAI_BASE_URL'] ?? https://api.openai.com/v1] - Override the default base URL for the API.
|
||
* @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
||
* @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections.
|
||
* @param {Core.Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
|
||
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
|
||
* @param {Core.Headers} opts.defaultHeaders - Default headers to include with every request to the API.
|
||
* @param {Core.DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API.
|
||
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
||
*/
|
||
constructor({ baseURL = readEnv("OPENAI_BASE_URL"), apiKey = readEnv("OPENAI_API_KEY"), organization = ((_a2) => (_a2 = readEnv("OPENAI_ORG_ID")) != null ? _a2 : null)(), project = ((_b) => (_b = readEnv("OPENAI_PROJECT_ID")) != null ? _b : null)(), ...opts } = {}) {
|
||
var _a3;
|
||
if (apiKey === void 0) {
|
||
throw new OpenAIError("The OPENAI_API_KEY environment variable is missing or empty; either provide it, or instantiate the OpenAI client with an apiKey option, like new OpenAI({ apiKey: 'My API Key' }).");
|
||
}
|
||
const options = {
|
||
apiKey,
|
||
organization,
|
||
project,
|
||
...opts,
|
||
baseURL: baseURL || `https://api.openai.com/v1`
|
||
};
|
||
if (!options.dangerouslyAllowBrowser && isRunningInBrowser()) {
|
||
throw new OpenAIError("It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew OpenAI({ apiKey, dangerouslyAllowBrowser: true });\n\nhttps://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety\n");
|
||
}
|
||
super({
|
||
baseURL: options.baseURL,
|
||
timeout: (_a3 = options.timeout) != null ? _a3 : 6e5,
|
||
httpAgent: options.httpAgent,
|
||
maxRetries: options.maxRetries,
|
||
fetch: options.fetch
|
||
});
|
||
this.completions = new Completions3(this);
|
||
this.chat = new Chat(this);
|
||
this.embeddings = new Embeddings(this);
|
||
this.files = new Files2(this);
|
||
this.images = new Images(this);
|
||
this.audio = new Audio(this);
|
||
this.moderations = new Moderations(this);
|
||
this.models = new Models(this);
|
||
this.fineTuning = new FineTuning(this);
|
||
this.beta = new Beta(this);
|
||
this.batches = new Batches(this);
|
||
this.uploads = new Uploads(this);
|
||
this._options = options;
|
||
this.apiKey = apiKey;
|
||
this.organization = organization;
|
||
this.project = project;
|
||
}
|
||
defaultQuery() {
|
||
return this._options.defaultQuery;
|
||
}
|
||
defaultHeaders(opts) {
|
||
return {
|
||
...super.defaultHeaders(opts),
|
||
"OpenAI-Organization": this.organization,
|
||
"OpenAI-Project": this.project,
|
||
...this._options.defaultHeaders
|
||
};
|
||
}
|
||
authHeaders(opts) {
|
||
return { Authorization: `Bearer ${this.apiKey}` };
|
||
}
|
||
stringifyQuery(query) {
|
||
return stringify(query, { arrayFormat: "brackets" });
|
||
}
|
||
};
|
||
_a = OpenAI;
|
||
OpenAI.OpenAI = _a;
|
||
OpenAI.DEFAULT_TIMEOUT = 6e5;
|
||
OpenAI.OpenAIError = OpenAIError;
|
||
OpenAI.APIError = APIError;
|
||
OpenAI.APIConnectionError = APIConnectionError;
|
||
OpenAI.APIConnectionTimeoutError = APIConnectionTimeoutError;
|
||
OpenAI.APIUserAbortError = APIUserAbortError;
|
||
OpenAI.NotFoundError = NotFoundError;
|
||
OpenAI.ConflictError = ConflictError;
|
||
OpenAI.RateLimitError = RateLimitError;
|
||
OpenAI.BadRequestError = BadRequestError;
|
||
OpenAI.AuthenticationError = AuthenticationError;
|
||
OpenAI.InternalServerError = InternalServerError;
|
||
OpenAI.PermissionDeniedError = PermissionDeniedError;
|
||
OpenAI.UnprocessableEntityError = UnprocessableEntityError;
|
||
OpenAI.toFile = toFile;
|
||
OpenAI.fileFromPath = fileFromPath;
|
||
OpenAI.Completions = Completions3;
|
||
OpenAI.Chat = Chat;
|
||
OpenAI.Embeddings = Embeddings;
|
||
OpenAI.Files = Files2;
|
||
OpenAI.FileObjectsPage = FileObjectsPage;
|
||
OpenAI.Images = Images;
|
||
OpenAI.Audio = Audio;
|
||
OpenAI.Moderations = Moderations;
|
||
OpenAI.Models = Models;
|
||
OpenAI.ModelsPage = ModelsPage;
|
||
OpenAI.FineTuning = FineTuning;
|
||
OpenAI.Beta = Beta;
|
||
OpenAI.Batches = Batches;
|
||
OpenAI.BatchesPage = BatchesPage;
|
||
OpenAI.Uploads = Uploads;
|
||
var openai_default = OpenAI;
|
||
|
||
// src/services/ai-service.ts
|
||
var import_obsidian = require("obsidian");
|
||
|
||
// src/services/logger.ts
|
||
var _Logger = class _Logger {
|
||
constructor(context) {
|
||
this.prefix = `[${context}]`;
|
||
}
|
||
// 只在开发环境下输出调试信息
|
||
debug(...args) {
|
||
if (_Logger.isDevelopment) {
|
||
console.log(this.prefix, ...args);
|
||
}
|
||
}
|
||
// 警告信息,生产环境也会输出
|
||
warn(...args) {
|
||
console.warn(this.prefix, ...args);
|
||
}
|
||
// 错误信息,生产环境也会输出
|
||
error(...args) {
|
||
console.error(this.prefix, ...args);
|
||
}
|
||
};
|
||
_Logger.isDevelopment = false;
|
||
var Logger = _Logger;
|
||
|
||
// src/services/ai-service.ts
|
||
var GEMINI_MODELS = {
|
||
"Gemini 1.5 Flash": "gemini-1.5-flash",
|
||
"Gemini 1.5 Flash-8B": "gemini-1.5-flash-8b",
|
||
"Gemini 1.5 Pro": "gemini-1.5-pro",
|
||
"Gemini 1.0 Pro": "gemini-1.0-pro",
|
||
"Text Embedding": "text-embedding-004",
|
||
"AQA": "aqa",
|
||
"\u81EA\u5B9A\u4E49\u6A21\u578B": "custom"
|
||
// 新增:自定义模型选项
|
||
};
|
||
var OPENAI_MODELS = {
|
||
// GPT-4o 系列
|
||
"GPT-4o": "gpt-4o",
|
||
"GPT-4o (2024-11-20)": "gpt-4o-2024-11-20",
|
||
"GPT-4o Mini": "gpt-4o-mini",
|
||
"GPT-4o Mini (2024-07-18)": "gpt-4o-mini-2024-07-18",
|
||
"GPT-4o Realtime": "gpt-4o-realtime-preview",
|
||
"GPT-4o Realtime (2024-10-01)": "gpt-4o-realtime-preview-2024-10-01",
|
||
"ChatGPT-4o Latest": "chatgpt-4o-latest",
|
||
"\u81EA\u5B9A\u4E49\u6A21\u578B": "custom"
|
||
// 已添加
|
||
};
|
||
var OLLAMA_MODELS = {
|
||
"Llama 2": "llama2",
|
||
"Mistral": "mistral",
|
||
"Mixtral": "mixtral",
|
||
"CodeLlama": "codellama",
|
||
"Phi": "phi",
|
||
"Neural Chat": "neural-chat",
|
||
"\u81EA\u5B9A\u4E49\u6A21\u578B": "custom"
|
||
};
|
||
var MODEL_DESCRIPTIONS = {
|
||
// Gemini Models
|
||
"gemini-1.5-flash": "\u97F3\u9891\u3001\u56FE\u7247\u3001\u89C6\u9891\u548C\u6587\u672C",
|
||
"gemini-1.5-flash-8b": "\u97F3\u9891\u3001\u56FE\u7247\u3001\u89C6\u9891\u548C\u6587\u672C",
|
||
"gemini-1.5-pro": "\u97F3\u9891\u3001\u56FE\u7247\u3001\u89C6\u9891\u548C\u6587\u672C",
|
||
"gemini-1.0-pro": "\u6587\u672C (\u5C06\u4E8E 2025 \u5E74 2 \u6708 15 \u65E5\u5F03\u7528)",
|
||
"text-embedding-004": "\u6587\u672C",
|
||
"aqa": "\u6587\u672C",
|
||
"custom": "\u81EA\u5B9A\u4E49\u6A21\u578B",
|
||
// OpenAI Models
|
||
"gpt-4o": "\u6807\u51C6\u7248 GPT-4o\uFF0C\u5F3A\u5927\u7684\u63A8\u7406\u80FD\u529B",
|
||
"gpt-4o-2024-11-20": "11\u6708\u5FEB\u7167\u7248\u672C\uFF0C\u7A33\u5B9A\u53EF\u9760",
|
||
"gpt-4o-mini": "\u8F7B\u91CF\u7EA7\u7248\u672C\uFF0C\u6027\u4EF7\u6BD4\u9AD8",
|
||
"gpt-4o-mini-2024-07-18": "Mini \u6A21\u578B\u7684\u7A33\u5B9A\u5FEB\u7167\u7248\u672C",
|
||
"gpt-4o-realtime-preview": "\u5B9E\u65F6\u9884\u89C8\u7248\u672C\uFF0C\u652F\u6301\u6700\u65B0\u7279\u6027",
|
||
"gpt-4o-realtime-preview-2024-10-01": "\u5B9E\u65F6\u9884\u89C8\u7684\u7A33\u5B9A\u5FEB\u7167\u7248\u672C",
|
||
"chatgpt-4o-latest": "ChatGPT \u4F7F\u7528\u7684\u6700\u65B0\u7248\u672C\uFF0C\u6301\u7EED\u66F4\u65B0",
|
||
// Ollama Models
|
||
"llama2": "Llama 2 - \u901A\u7528\u5927\u8BED\u8A00\u6A21\u578B",
|
||
"mistral": "Mistral - \u9AD8\u6027\u80FD\u5F00\u6E90\u6A21\u578B",
|
||
"mixtral": "Mixtral - \u6DF7\u5408\u4E13\u5BB6\u6A21\u578B",
|
||
"codellama": "CodeLlama - \u4EE3\u7801\u751F\u6210\u4E13\u7528\u6A21\u578B",
|
||
"phi": "Phi - \u8F7B\u91CF\u7EA7\u6A21\u578B",
|
||
"neural-chat": "Neural Chat - \u5BF9\u8BDD\u4F18\u5316\u6A21\u578B"
|
||
};
|
||
var MAX_RETRIES = 3;
|
||
var RETRY_DELAY = 1e3;
|
||
async function sleep2(ms) {
|
||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||
}
|
||
async function retryWithBackoff(operation, maxRetries = MAX_RETRIES, initialDelay = RETRY_DELAY) {
|
||
for (let i = 0; i < maxRetries; i++) {
|
||
try {
|
||
return await operation();
|
||
} catch (error) {
|
||
if (error instanceof Error && error.message.includes("429")) {
|
||
const delay2 = initialDelay * 2 ** i;
|
||
await sleep2(delay2);
|
||
continue;
|
||
}
|
||
if (i === maxRetries - 1) {
|
||
throw error;
|
||
}
|
||
const delay = initialDelay * 2 ** i;
|
||
await sleep2(delay);
|
||
}
|
||
}
|
||
throw new Error("\u91CD\u8BD5\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650");
|
||
}
|
||
var GeminiService = class {
|
||
constructor(apiKey, modelName) {
|
||
const genAI = new GoogleGenerativeAI(apiKey);
|
||
this.model = genAI.getGenerativeModel({ model: modelName || GEMINI_MODELS["Gemini 1.5 Flash"] });
|
||
this.logger = new Logger("GeminiService");
|
||
}
|
||
async initialize(apiKey, modelName) {
|
||
this.logger.debug("Gemini \u670D\u52A1\u521D\u59CB\u5316\u6210\u529F\uFF0C\u4F7F\u7528\u6A21\u578B:", this.model);
|
||
}
|
||
async handleRateLimit(error, retryCount) {
|
||
const delay = Math.min(1e3 * 2 ** retryCount, 3e4);
|
||
this.logger.warn(`\u914D\u989D\u9650\u5236\uFF0C\u7B49\u5F85 ${delay}ms \u540E\u91CD\u8BD5...`);
|
||
return delay;
|
||
}
|
||
async handleError(error, retryCount) {
|
||
const delay = Math.min(1e3 * 2 ** retryCount, 3e4);
|
||
this.logger.error(`\u64CD\u4F5C\u5931\u8D25\uFF0C\u7B49\u5F85 ${delay}ms \u540E\u91CD\u8BD5...`, error);
|
||
return delay;
|
||
}
|
||
async generateSummary(content, language = "zh") {
|
||
const prompt = `\u8BF7\u7528${language === "zh" ? "\u4E2D\u6587" : "English"}\u603B\u7ED3\u4EE5\u4E0B\u5185\u5BB9\u7684\u8981\u70B9\uFF1A
|
||
|
||
${content}`;
|
||
return retryWithBackoff(async () => {
|
||
const result = await this.model.generateContent(prompt);
|
||
const response = await result.response;
|
||
return response.text().trim();
|
||
});
|
||
}
|
||
async generateTags(content) {
|
||
const prompt = `\u8BF7\u4E3A\u4EE5\u4E0B\u5185\u5BB9\u751F\u62103-5\u4E2A\u76F8\u5173\u6807\u7B7E\uFF08\u4E0D\u8981\u5E26#\u53F7\uFF09\uFF1A
|
||
|
||
${content}`;
|
||
return retryWithBackoff(async () => {
|
||
const result = await this.model.generateContent(prompt);
|
||
const response = await result.response;
|
||
return response.text().split(/[,,\s]+/).filter(Boolean);
|
||
});
|
||
}
|
||
async generateWeeklyDigest(contents) {
|
||
const combinedContent = contents.join("\n---\n");
|
||
const prompt = `\u8BF7\u5BF9\u4E0B\u4E00\u5468\u7684\u5185\u5BB9\u8FDB\u884C\u603B\u7ED3\u548C\u5206\u6790\uFF0C\u751F\u6210\u4E00\u4EFD\u5468\u62A5\u3002\u91CD\u70B9\u5173\u6CE8\uFF1A
|
||
1. \u4E3B\u8981\u5DE5\u4F5C\u5185\u5BB9\u548C\u6210\u679C
|
||
2. \u91CD\u8981\u4E8B\u9879\u548C\u8FDB\u5C55
|
||
3. \u95EE\u9898\u548C\u89E3\u51B3\u65B9\u6848
|
||
4. \u4E0B\u5468\u8BA1\u5212\u548C\u5C55\u671B
|
||
|
||
\u5185\u5BB9\uFF1A
|
||
${combinedContent}`;
|
||
return retryWithBackoff(async () => {
|
||
const result = await this.model.generateContent(prompt);
|
||
const response = await result.response;
|
||
return response.text().trim();
|
||
});
|
||
}
|
||
};
|
||
var OpenAIService = class {
|
||
// 生成随机 IV
|
||
async generateIV() {
|
||
return crypto.getRandomValues(new Uint8Array(12));
|
||
}
|
||
// 生成加密密钥
|
||
async generateKey() {
|
||
return crypto.subtle.generateKey(
|
||
{
|
||
name: "AES-GCM",
|
||
length: 256
|
||
},
|
||
true,
|
||
["encrypt", "decrypt"]
|
||
);
|
||
}
|
||
// 加密 API 密钥
|
||
async encryptApiKey(apiKey) {
|
||
const iv = await this.generateIV();
|
||
const key = await this.generateKey();
|
||
const encodedText = new TextEncoder().encode(apiKey);
|
||
const encryptedData = await crypto.subtle.encrypt(
|
||
{
|
||
name: "AES-GCM",
|
||
iv
|
||
},
|
||
key,
|
||
encodedText
|
||
);
|
||
const encryptedArray = new Uint8Array(encryptedData);
|
||
return `${this.arrayBufferToBase64(iv)}:${this.arrayBufferToBase64(encryptedArray)}:${this.arrayBufferToBase64(await crypto.subtle.exportKey("raw", key))}`;
|
||
}
|
||
// 解密 API 密钥
|
||
async decryptApiKey(encryptedKey) {
|
||
const [ivStr, encryptedStr, keyStr] = encryptedKey.split(":");
|
||
const iv = this.base64ToArrayBuffer(ivStr);
|
||
const encryptedData = this.base64ToArrayBuffer(encryptedStr);
|
||
const keyData = this.base64ToArrayBuffer(keyStr);
|
||
const key = await crypto.subtle.importKey(
|
||
"raw",
|
||
keyData,
|
||
"AES-GCM",
|
||
true,
|
||
["decrypt"]
|
||
);
|
||
const decryptedData = await crypto.subtle.decrypt(
|
||
{
|
||
name: "AES-GCM",
|
||
iv
|
||
},
|
||
key,
|
||
encryptedData
|
||
);
|
||
return new TextDecoder().decode(decryptedData);
|
||
}
|
||
arrayBufferToBase64(buffer) {
|
||
const bytes = new Uint8Array(buffer);
|
||
let binary = "";
|
||
for (let i = 0; i < bytes.byteLength; i++) {
|
||
binary += String.fromCharCode(bytes[i]);
|
||
}
|
||
return window.btoa(binary);
|
||
}
|
||
base64ToArrayBuffer(base64) {
|
||
const binaryString = window.atob(base64);
|
||
const bytes = new Uint8Array(binaryString.length);
|
||
for (let i = 0; i < binaryString.length; i++) {
|
||
bytes[i] = binaryString.charCodeAt(i);
|
||
}
|
||
return bytes;
|
||
}
|
||
constructor() {
|
||
this.encryptionKey = crypto.getRandomValues(new Uint8Array(32));
|
||
this.logger = new Logger("OpenAIService");
|
||
}
|
||
async initialize(apiKey, modelName, openaiBaseUrl) {
|
||
try {
|
||
if (!apiKey) {
|
||
throw new Error("API \u5BC6\u94A5\u4E0D\u80FD\u4E3A\u7A7A");
|
||
}
|
||
if (!apiKey.startsWith("sk-") || apiKey.length < 20) {
|
||
throw new Error("\u65E0\u6548\u7684 API \u5BC6\u94A5\u683C\u5F0F");
|
||
}
|
||
const encryptedKey = await this.encryptApiKey(apiKey);
|
||
this.client = new openai_default({
|
||
apiKey: await this.decryptApiKey(encryptedKey),
|
||
baseURL: openaiBaseUrl,
|
||
dangerouslyAllowBrowser: true
|
||
});
|
||
try {
|
||
await this.client.models.list();
|
||
} catch (error) {
|
||
throw new Error("API \u5BC6\u94A5\u9A8C\u8BC1\u5931\u8D25");
|
||
}
|
||
this.model = modelName || OPENAI_MODELS["GPT-4o"];
|
||
this.logger.debug("OpenAI \u670D\u52A1\u521D\u59CB\u5316\u6210\u529F\uFF0C\u4F7F\u7528\u6A21\u578B:", this.model);
|
||
new import_obsidian.Notice(`AI \u670D\u52A1\u521D\u59CB\u5316\u6210\u529F`);
|
||
} catch (error) {
|
||
this.logger.error("OpenAI \u670D\u52A1\u521D\u59CB\u5316\u5931\u8D25:", error);
|
||
new import_obsidian.Notice(`AI \u670D\u52A1\u521D\u59CB\u5316\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
||
throw error;
|
||
}
|
||
}
|
||
async generateSummary(content, language = "zh") {
|
||
const prompt = `\u8BF7\u7528${language === "zh" ? "\u4E2D\u6587" : "English"}\u603B\u7ED3\u4EE5\u4E0B\u5185\u5BB9\u7684\u8981\u70B9\uFF1A
|
||
|
||
${content}`;
|
||
return retryWithBackoff(async () => {
|
||
var _a2, _b, _c;
|
||
const response = await this.client.chat.completions.create({
|
||
model: this.model,
|
||
messages: [{ role: "user", content: prompt }],
|
||
temperature: 0.7,
|
||
max_tokens: 500
|
||
});
|
||
return ((_c = (_b = (_a2 = response.choices[0]) == null ? void 0 : _a2.message) == null ? void 0 : _b.content) == null ? void 0 : _c.trim()) || "";
|
||
});
|
||
}
|
||
async generateTags(content) {
|
||
const prompt = `\u8BF7\u4E3A\u4EE5\u4E0B\u5185\u5BB9\u751F\u62103-5\u4E2A\u76F8\u5173\u6807\u7B7E\uFF08\u4E0D\u8981\u5E26#\u53F7\uFF09\uFF1A
|
||
|
||
${content}`;
|
||
return retryWithBackoff(async () => {
|
||
var _a2, _b;
|
||
const response = await this.client.chat.completions.create({
|
||
model: this.model,
|
||
messages: [{ role: "user", content: prompt }],
|
||
temperature: 0.7,
|
||
max_tokens: 100
|
||
});
|
||
const text = ((_b = (_a2 = response.choices[0]) == null ? void 0 : _a2.message) == null ? void 0 : _b.content) || "";
|
||
return text.split(/[,,\s]+/).filter(Boolean);
|
||
});
|
||
}
|
||
async generateWeeklyDigest(contents) {
|
||
const combinedContent = contents.join("\n---\n");
|
||
const prompt = `\u8BF7\u5BF9\u4EE5\u4E0B\u4E00\u5468\u7684\u5185\u5BB9\u8FDB\u884C\u603B\u7ED3\u548C\u5206\u6790\uFF0C\u751F\u6210\u4E00\u4EFD\u5468\u62A5\u3002\u8981\u6C42\uFF1A
|
||
1. \u4E3B\u8981\u5DE5\u4F5C\u5185\u5BB9\u548C\u6210\u679C
|
||
2. \u91CD\u8981\u4E8B\u9879\u548C\u8FDB\u5C55
|
||
3. \u95EE\u9898\u548C\u89E3\u51B3\u65B9\u6848
|
||
4. \u4E0B\u5468\u8BA1\u5212\u548C\u5C55\u671B
|
||
|
||
\u5185\u5BB9\uFF1A
|
||
${combinedContent}`;
|
||
return retryWithBackoff(async () => {
|
||
var _a2, _b, _c;
|
||
const response = await this.client.chat.completions.create({
|
||
model: this.model,
|
||
messages: [{ role: "user", content: prompt }],
|
||
temperature: 0.7,
|
||
max_tokens: 1e3
|
||
});
|
||
return ((_c = (_b = (_a2 = response.choices[0]) == null ? void 0 : _a2.message) == null ? void 0 : _b.content) == null ? void 0 : _c.trim()) || "";
|
||
});
|
||
}
|
||
};
|
||
var OllamaService = class {
|
||
constructor(baseUrl = "http://localhost:11434", modelName) {
|
||
this.baseUrl = baseUrl;
|
||
this.model = modelName || OLLAMA_MODELS["Llama 2"];
|
||
this.logger = new Logger("OllamaService");
|
||
}
|
||
async initialize(apiKey, modelName) {
|
||
this.logger.debug("Ollama \u670D\u52A1\u521D\u59CB\u5316\u6210\u529F\uFF0C\u4F7F\u7528\u6A21\u578B:", this.model);
|
||
}
|
||
async handleRateLimit(error, retryCount) {
|
||
const delay = Math.min(1e3 * 2 ** retryCount, 3e4);
|
||
this.logger.warn(`\u914D\u989D\u9650\u5236\uFF0C\u7B49\u5F85 ${delay}ms \u540E\u91CD\u8BD5...`);
|
||
return delay;
|
||
}
|
||
async handleError(error, retryCount) {
|
||
const delay = Math.min(1e3 * 2 ** retryCount, 3e4);
|
||
this.logger.error(`\u64CD\u4F5C\u5931\u8D25\uFF0C\u7B49\u5F85 ${delay}ms \u540E\u91CD\u8BD5...`, error);
|
||
return delay;
|
||
}
|
||
async generateCompletion(prompt) {
|
||
try {
|
||
const response = await (0, import_obsidian.requestUrl)({
|
||
url: `${this.baseUrl}/api/generate`,
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
model: this.model,
|
||
prompt,
|
||
stream: false,
|
||
options: {
|
||
temperature: 0.7,
|
||
top_p: 0.9,
|
||
max_tokens: 1e3
|
||
}
|
||
})
|
||
});
|
||
if (response.status !== 200) {
|
||
throw new Error(`Ollama API error: ${response.status}`);
|
||
}
|
||
const data = response.json;
|
||
return data.response;
|
||
} catch (error) {
|
||
this.logger.error("Ollama API error:", error);
|
||
throw error;
|
||
}
|
||
}
|
||
async generateSummary(content, language = "zh") {
|
||
const prompt = `\u8BF7\u7528${language === "zh" ? "\u4E2D\u6587" : "English"}\u603B\u7ED3\u4EE5\u4E0B\u5185\u5BB9\u7684\u8981\u70B9\uFF1A
|
||
|
||
${content}`;
|
||
return retryWithBackoff(async () => {
|
||
const response = await this.generateCompletion(prompt);
|
||
return response.trim();
|
||
});
|
||
}
|
||
async generateTags(content) {
|
||
const prompt = `\u8BF7\u4E3A\u4EE5\u4E0B\u5185\u5BB9\u751F\u62103-5\u4E2A\u76F8\u5173\u6807\u7B7E\uFF08\u4E0D\u8981\u5E26#\u53F7\uFF09\uFF1A
|
||
|
||
${content}`;
|
||
return retryWithBackoff(async () => {
|
||
const response = await this.generateCompletion(prompt);
|
||
return response.split(/[,,\s]+/).filter(Boolean);
|
||
});
|
||
}
|
||
async generateWeeklyDigest(contents) {
|
||
const combinedContent = contents.join("\n---\n");
|
||
const prompt = `\u8BF7\u5BF9\u4EE5\u4E0B\u4E00\u5468\u7684\u5185\u5BB9\u8FDB\u884C\u603B\u7ED3\u548C\u5206\u6790\uFF0C\u751F\u6210\u4E00\u4EFD\u5468\u62A5\u3002\u8981\u6C42\uFF1A
|
||
1. \u4E3B\u8981\u5DE5\u4F5C\u5185\u5BB9\u548C\u6210\u679C
|
||
2. \u91CD\u8981\u4E8B\u9879\u548C\u8FDB\u5C55
|
||
3. \u95EE\u9898\u548C\u89E3\u51B3\u65B9\u6848
|
||
4. \u4E0B\u5468\u8BA1\u5212\u548C\u5C55\u671B
|
||
|
||
\u5185\u5BB9\uFF1A
|
||
${combinedContent}`;
|
||
return retryWithBackoff(async () => {
|
||
const response = await this.generateCompletion(prompt);
|
||
return response.trim();
|
||
});
|
||
}
|
||
};
|
||
function createAIService(type, apiKey, modelName, openaiBaseUrl) {
|
||
const serviceType = type.toLowerCase();
|
||
switch (serviceType) {
|
||
case "gemini": {
|
||
const service = new GeminiService(apiKey, modelName);
|
||
void service.initialize(apiKey, modelName);
|
||
return service;
|
||
}
|
||
case "openai": {
|
||
const service = new OpenAIService();
|
||
void service.initialize(apiKey, modelName, openaiBaseUrl);
|
||
return service;
|
||
}
|
||
case "ollama": {
|
||
const service = new OllamaService(apiKey || "http://localhost:11434", modelName);
|
||
void service.initialize(apiKey, modelName);
|
||
return service;
|
||
}
|
||
default: {
|
||
const service = createDummyAIService();
|
||
void service.initialize("", "");
|
||
return service;
|
||
}
|
||
}
|
||
}
|
||
function createDummyAIService() {
|
||
const logger = new Logger("DummyAIService");
|
||
return {
|
||
async generateSummary() {
|
||
logger.debug("\u4F7F\u7528\u7A7A AI \u670D\u52A1");
|
||
return "";
|
||
},
|
||
async generateTags() {
|
||
logger.debug("\u4F7F\u7528\u7A7A AI \u670D\u52A1");
|
||
return [];
|
||
},
|
||
async generateWeeklyDigest() {
|
||
logger.debug("\u4F7F\u7528\u7A7A AI \u670D\u52A1");
|
||
return "";
|
||
},
|
||
async initialize() {
|
||
logger.debug("\u521D\u59CB\u5316\u7A7A AI \u670D\u52A1");
|
||
}
|
||
};
|
||
}
|
||
|
||
// src/ui/settings-tab.ts
|
||
var MemosSyncSettingTab = class extends import_obsidian2.PluginSettingTab {
|
||
constructor(app, plugin) {
|
||
super(app, plugin);
|
||
this.plugin = plugin;
|
||
}
|
||
display() {
|
||
const { containerEl } = this;
|
||
containerEl.empty();
|
||
new import_obsidian2.Setting(containerEl).setName("Memos API URL").setDesc("\u60A8\u7684 Memos \u670D\u52A1\u5668 API \u5730\u5740,\u683C\u5F0F\u5982\uFF1Ahttps://memose.com/api/v1 ").addText((text) => text.setPlaceholder("https://x.com/api/v1").setValue(this.plugin.settings.memosApiUrl).onChange(async (value) => {
|
||
this.plugin.settings.memosApiUrl = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("\u8BBF\u95EE\u4EE4\u724C").setDesc("\u60A8\u7684 Memos API \u8BBF\u95EE\u4EE4\u724C").addText((text) => text.setPlaceholder("\u8F93\u5165\u8BBF\u95EE\u4EE4\u724C").setValue(this.plugin.settings.memosAccessToken).onChange(async (value) => {
|
||
this.plugin.settings.memosAccessToken = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("\u540C\u6B65\u76EE\u5F55").setDesc("Memos \u5185\u5BB9\u5728 Obsidian \u4E2D\u7684\u5B58\u50A8\u4F4D\u7F6E").addText((text) => text.setPlaceholder("\u4F8B\u5982\uFF1Amemos").setValue(this.plugin.settings.syncDirectory).onChange(async (value) => {
|
||
this.plugin.settings.syncDirectory = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("\u540C\u6B65\u6A21\u5F0F").setDesc("\u9009\u62E9\u624B\u52A8\u540C\u6B65\u6216\u81EA\u52A8\u540C\u6B65").addDropdown((dropdown) => dropdown.addOption("manual", "\u624B\u52A8\u540C\u6B65").addOption("auto", "\u81EA\u52A8\u540C\u6B65").setValue(this.plugin.settings.syncFrequency).onChange(async (value) => {
|
||
this.plugin.settings.syncFrequency = value;
|
||
await this.plugin.saveSettings();
|
||
this.display();
|
||
}));
|
||
if (this.plugin.settings.syncFrequency === "auto") {
|
||
new import_obsidian2.Setting(containerEl).setName("\u540C\u6B65\u95F4\u9694").setDesc("\u81EA\u52A8\u540C\u6B65\u7684\u65F6\u95F4\u95F4\u9694\uFF08\u5206\u949F\uFF09").addText((text) => text.setPlaceholder("\u4F8B\u5982\uFF1A30").setValue(String(this.plugin.settings.autoSyncInterval)).onChange(async (value) => {
|
||
const interval = Number.parseInt(value, 10);
|
||
if (Number.isFinite(interval) && interval > 0) {
|
||
this.plugin.settings.autoSyncInterval = interval;
|
||
await this.plugin.saveSettings();
|
||
}
|
||
}));
|
||
}
|
||
new import_obsidian2.Setting(containerEl).setName("\u540C\u6B65\u6761\u6570").setDesc("\u6BCF\u6B21\u540C\u6B65\u7684\u6700\u5927\u6761\u76EE\u6570").addText((text) => text.setPlaceholder("\u4F8B\u5982\uFF1A100").setValue(String(this.plugin.settings.syncLimit)).onChange(async (value) => {
|
||
const limit2 = Number.parseInt(value, 10);
|
||
if (Number.isFinite(limit2) && limit2 > 0) {
|
||
this.plugin.settings.syncLimit = limit2;
|
||
await this.plugin.saveSettings();
|
||
}
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("\u542F\u7528 AI \u529F\u80FD").setDesc("\u5F00\u542F\u6216\u5173\u95ED AI \u589E\u5F3A\u529F\u80FD").addToggle((toggle) => toggle.setValue(this.plugin.settings.ai.enabled).onChange(async (value) => {
|
||
this.plugin.settings.ai.enabled = value;
|
||
await this.plugin.saveSettings();
|
||
this.display();
|
||
}));
|
||
if (this.plugin.settings.ai.enabled) {
|
||
new import_obsidian2.Setting(containerEl).setName("AI \u6A21\u578B").setDesc("\u9009\u62E9\u8981\u4F7F\u7528\u7684 AI \u6A21\u578B").addDropdown((dropdown) => dropdown.addOption("openai", "OpenAI").addOption("gemini", "Google Gemini").addOption("claude", "Anthropic Claude").addOption("ollama", "Ollama").setValue(this.plugin.settings.ai.modelType).onChange(async (value) => {
|
||
this.plugin.settings.ai.modelType = value;
|
||
await this.plugin.saveSettings();
|
||
this.display();
|
||
}));
|
||
if (this.plugin.settings.ai.modelType !== "ollama") {
|
||
new import_obsidian2.Setting(containerEl).setName("API \u5BC6\u94A5").setDesc("\u60A8\u7684 AI \u670D\u52A1 API \u5BC6\u94A5").addText((text) => text.setPlaceholder("\u8F93\u5165 API \u5BC6\u94A5").setValue(this.plugin.settings.ai.apiKey).onChange(async (value) => {
|
||
this.plugin.settings.ai.apiKey = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
}
|
||
this.displayModelOptions(containerEl);
|
||
new import_obsidian2.Setting(containerEl).setName("\u6BCF\u5468\u6C47\u603B").setDesc("\u81EA\u52A8\u751F\u6210\u6BCF\u5468\u5185\u5BB9\u6C47\u603B").addToggle((toggle) => toggle.setValue(this.plugin.settings.ai.weeklyDigest).onChange(async (value) => {
|
||
this.plugin.settings.ai.weeklyDigest = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("\u81EA\u52A8\u6807\u7B7E").setDesc("\u6839\u636E\u5185\u5BB9\u81EA\u52A8\u751F\u6210\u6807\u7B7E").addToggle((toggle) => toggle.setValue(this.plugin.settings.ai.autoTags).onChange(async (value) => {
|
||
this.plugin.settings.ai.autoTags = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("\u667A\u80FD\u6458\u8981").setDesc("\u81EA\u52A8\u751F\u6210\u5185\u5BB9\u6458\u8981").addToggle((toggle) => toggle.setValue(this.plugin.settings.ai.intelligentSummary).onChange(async (value) => {
|
||
this.plugin.settings.ai.intelligentSummary = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("\u6458\u8981\u8BED\u8A00").setDesc("\u9009\u62E9\u6458\u8981\u751F\u6210\u7684\u8BED\u8A00").addDropdown((dropdown) => dropdown.addOption("zh", "\u4E2D\u6587").addOption("en", "\u82F1\u6587").addOption("ja", "\u65E5\u6587").addOption("ko", "\u97E9\u6587").setValue(this.plugin.settings.ai.summaryLanguage).onChange(async (value) => {
|
||
this.plugin.settings.ai.summaryLanguage = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
}
|
||
}
|
||
displayModelOptions(containerEl) {
|
||
const modelType = this.plugin.settings.ai.modelType;
|
||
if (modelType === "gemini") {
|
||
new import_obsidian2.Setting(containerEl).setName("Gemini \u6A21\u578B").setDesc("\u9009\u62E9\u8981\u4F7F\u7528\u7684 Gemini \u6A21\u578B").addDropdown((dropdown) => {
|
||
for (const [displayName, modelId] of Object.entries(GEMINI_MODELS)) {
|
||
dropdown.addOption(modelId, `${displayName} - ${MODEL_DESCRIPTIONS[modelId]}`);
|
||
}
|
||
const currentModel = this.plugin.settings.ai.modelName || GEMINI_MODELS["Gemini 1.5 Flash"];
|
||
dropdown.setValue(currentModel);
|
||
dropdown.onChange(async (value) => {
|
||
this.plugin.settings.ai.modelName = value;
|
||
await this.plugin.saveSettings();
|
||
this.display();
|
||
});
|
||
});
|
||
if (this.plugin.settings.ai.modelName === "custom") {
|
||
new import_obsidian2.Setting(containerEl).setName("\u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0").setDesc("\u8F93\u5165\u8981\u4F7F\u7528\u7684\u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0").addText((text) => text.setPlaceholder("\u4F8B\u5982\uFF1Agemini-pro-latest").setValue(this.plugin.settings.ai.customModelName).onChange(async (value) => {
|
||
this.plugin.settings.ai.customModelName = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
}
|
||
} else if (modelType === "openai") {
|
||
new import_obsidian2.Setting(containerEl).setName("OpenAI \u6A21\u578B").setDesc("\u9009\u62E9\u8981\u4F7F\u7528\u7684 OpenAI \u6A21\u578B").addDropdown((dropdown) => {
|
||
for (const [displayName, modelId] of Object.entries(OPENAI_MODELS)) {
|
||
dropdown.addOption(modelId, `${displayName} - ${MODEL_DESCRIPTIONS[modelId]}`);
|
||
}
|
||
const currentModel = this.plugin.settings.ai.modelName || OPENAI_MODELS["GPT-4o"];
|
||
dropdown.setValue(currentModel);
|
||
dropdown.onChange(async (value) => {
|
||
this.plugin.settings.ai.modelName = value;
|
||
await this.plugin.saveSettings();
|
||
this.display();
|
||
});
|
||
});
|
||
if (this.plugin.settings.ai.modelName === "custom") {
|
||
new import_obsidian2.Setting(containerEl).setName("\u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0").setDesc("\u8F93\u5165\u8981\u4F7F\u7528\u7684\u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0").addText((text) => text.setPlaceholder("\u4F8B\u5982\uFF1Agpt-4-1106-preview").setValue(this.plugin.settings.ai.customModelName).onChange(async (value) => {
|
||
this.plugin.settings.ai.customModelName = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("OpenAI API \u57FA\u7840\u94FE\u63A5").setDesc("\u5982\u679C\u4F7F\u7528\u81EA\u5B9A\u4E49 API \u670D\u52A1\uFF0C\u8BF7\u8BBE\u7F6E\u5BF9\u5E94\u7684\u57FA\u7840\u94FE\u63A5").addText((text) => text.setPlaceholder("https://api.openai.com/v1").setValue(this.plugin.settings.ai.openaiBaseUrl || "https://api.openai.com/v1").onChange(async (value) => {
|
||
this.plugin.settings.ai.openaiBaseUrl = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
}
|
||
} else if (modelType === "claude") {
|
||
new import_obsidian2.Setting(containerEl).setName("Claude \u6A21\u578B").setDesc("\u9009\u62E9\u8981\u4F7F\u7528\u7684 Claude \u6A21\u578B").addDropdown((dropdown) => {
|
||
dropdown.addOption("claude-3-opus-20240229", "Claude 3 Opus").addOption("claude-3-sonnet-20240229", "Claude 3 Sonnet").addOption("claude-3-haiku-20240307", "Claude 3 Haiku").addOption("custom", "\u81EA\u5B9A\u4E49\u6A21\u578B - \u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0");
|
||
const currentModel = this.plugin.settings.ai.modelName || "claude-3-opus-20240229";
|
||
dropdown.setValue(currentModel);
|
||
dropdown.onChange(async (value) => {
|
||
this.plugin.settings.ai.modelName = value;
|
||
await this.plugin.saveSettings();
|
||
this.display();
|
||
});
|
||
});
|
||
if (this.plugin.settings.ai.modelName === "custom") {
|
||
new import_obsidian2.Setting(containerEl).setName("\u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0").setDesc("\u8F93\u5165\u8981\u4F7F\u7528\u7684\u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0").addText((text) => text.setPlaceholder("\u4F8B\u5982\uFF1Aclaude-3-opus-next").setValue(this.plugin.settings.ai.customModelName).onChange(async (value) => {
|
||
this.plugin.settings.ai.customModelName = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
}
|
||
} else if (modelType === "ollama") {
|
||
new import_obsidian2.Setting(containerEl).setName("Ollama \u670D\u52A1\u5730\u5740").setDesc("\u8BBE\u7F6E Ollama \u670D\u52A1\u7684\u5730\u5740\uFF08\u9ED8\u8BA4\u4E3A http://localhost:11434\uFF09").addText((text) => text.setPlaceholder("http://localhost:11434").setValue(this.plugin.settings.ai.ollamaBaseUrl).onChange(async (value) => {
|
||
this.plugin.settings.ai.ollamaBaseUrl = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
new import_obsidian2.Setting(containerEl).setName("Ollama \u6A21\u578B").setDesc("\u9009\u62E9\u8981\u4F7F\u7528\u7684 Ollama \u6A21\u578B").addDropdown((dropdown) => {
|
||
for (const [displayName, modelId] of Object.entries(OLLAMA_MODELS)) {
|
||
if (typeof modelId === "string") {
|
||
dropdown.addOption(modelId, `${displayName} - ${MODEL_DESCRIPTIONS[modelId] || modelId}`);
|
||
}
|
||
}
|
||
const defaultModel = OLLAMA_MODELS["Llama 2"];
|
||
const currentModel = this.plugin.settings.ai.modelName || defaultModel;
|
||
dropdown.setValue(currentModel);
|
||
dropdown.onChange(async (value) => {
|
||
this.plugin.settings.ai.modelName = value;
|
||
await this.plugin.saveSettings();
|
||
this.display();
|
||
});
|
||
});
|
||
if (this.plugin.settings.ai.modelName === "custom") {
|
||
new import_obsidian2.Setting(containerEl).setName("\u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0").setDesc("\u8F93\u5165\u8981\u4F7F\u7528\u7684\u81EA\u5B9A\u4E49\u6A21\u578B\u540D\u79F0").addText((text) => text.setPlaceholder("\u4F8B\u5982\uFF1Allama2:13b").setValue(this.plugin.settings.ai.customModelName).onChange(async (value) => {
|
||
this.plugin.settings.ai.customModelName = value;
|
||
await this.plugin.saveSettings();
|
||
}));
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
// src/services/memos-service.ts
|
||
var import_obsidian3 = require("obsidian");
|
||
var MemosService = class {
|
||
constructor(apiUrl, accessToken, syncLimit) {
|
||
this.apiUrl = apiUrl;
|
||
this.accessToken = accessToken;
|
||
this.syncLimit = syncLimit;
|
||
this.logger = new Logger("MemosService");
|
||
}
|
||
async fetchAllMemos() {
|
||
try {
|
||
this.logger.debug("\u5F00\u59CB\u83B7\u53D6 memos\uFF0CAPI URL:", this.apiUrl);
|
||
this.logger.debug("Access Token:", this.accessToken ? "\u5DF2\u8BBE\u7F6E" : "\u672A\u8BBE\u7F6E");
|
||
this.logger.debug("\u540C\u6B65\u9650\u5236:", this.syncLimit, "\u6761");
|
||
const allMemos = [];
|
||
let pageToken;
|
||
const pageSize = Math.min(100, this.syncLimit);
|
||
if (!this.apiUrl.includes("/api/v1")) {
|
||
throw new Error("API URL \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u786E\u4FDD\u5305\u542B /api/v1");
|
||
}
|
||
do {
|
||
const baseUrl = this.apiUrl;
|
||
const url = `${baseUrl}/memos`;
|
||
const params = new URLSearchParams({
|
||
"state": "NORMAL",
|
||
"pageSize": pageSize.toString()
|
||
});
|
||
if (pageToken) {
|
||
params.set("pageToken", pageToken);
|
||
}
|
||
const finalUrl = `${url}?${params.toString()}`;
|
||
this.logger.debug("\u8BF7\u6C42 URL:", finalUrl);
|
||
const response = await (0, import_obsidian3.requestUrl)({
|
||
url: finalUrl,
|
||
headers: {
|
||
"Authorization": `Bearer ${this.accessToken}`,
|
||
"Accept": "application/json"
|
||
}
|
||
});
|
||
if (response.status !== 200) {
|
||
throw new Error(`HTTP ${response.status}: \u8BF7\u6C42\u5931\u8D25
|
||
\u54CD\u5E94\u5185\u5BB9: ${response.text}`);
|
||
}
|
||
const responseData = response.json;
|
||
this.logger.debug("API \u54CD\u5E94\u6570\u636E:", responseData);
|
||
if (!responseData || !Array.isArray(responseData.memos)) {
|
||
throw new Error("\u54CD\u5E94\u683C\u5F0F\u65E0\u6548: \u8FD4\u56DE\u6570\u636E\u4E0D\u5305\u542B memos \u6570\u7EC4");
|
||
}
|
||
const memos = responseData.memos;
|
||
pageToken = responseData.nextPageToken;
|
||
if (memos.length === 0) {
|
||
break;
|
||
}
|
||
const remainingCount = this.syncLimit - allMemos.length;
|
||
const neededCount = Math.min(memos.length, remainingCount);
|
||
allMemos.push(...memos.slice(0, neededCount));
|
||
this.logger.debug(`\u672C\u6B21\u83B7\u53D6 ${neededCount} \u6761 memos\uFF0C\u603B\u8BA1: ${allMemos.length}/${this.syncLimit}`);
|
||
if (allMemos.length >= this.syncLimit || !pageToken) {
|
||
break;
|
||
}
|
||
} while (true);
|
||
this.logger.debug(`\u6700\u7EC8\u8FD4\u56DE ${allMemos.length} \u6761 memos`);
|
||
return allMemos.sort(
|
||
(a, b) => new Date(b.createTime).getTime() - new Date(a.createTime).getTime()
|
||
);
|
||
} catch (error) {
|
||
this.logger.error("\u83B7\u53D6 memos \u5931\u8D25:", error);
|
||
if (error instanceof TypeError && error.message === "Failed to fetch") {
|
||
throw new Error(`\u7F51\u7EDC\u9519\u8BEF: \u65E0\u6CD5\u8FDE\u63A5\u5230 ${this.apiUrl}\u3002\u8BF7\u68C0\u67E5 URL \u662F\u5426\u6B63\u786E\u4E14\u53EF\u8BBF\u95EE\u3002`);
|
||
}
|
||
throw error;
|
||
}
|
||
}
|
||
async downloadResource(resource) {
|
||
try {
|
||
const attachmentId = resource.name.split("/").pop() || resource.name;
|
||
const resourceUrl = `${this.apiUrl.replace("/api/v1", "")}/file/attachments/${attachmentId}/${encodeURIComponent(resource.filename)}`;
|
||
this.logger.debug(`\u6B63\u5728\u4E0B\u8F7D\u8D44\u6E90: ${resourceUrl}`);
|
||
const response = await (0, import_obsidian3.requestUrl)({
|
||
url: resourceUrl,
|
||
headers: {
|
||
"Authorization": `Bearer ${this.accessToken}`,
|
||
"Accept": "*/*"
|
||
},
|
||
method: "GET"
|
||
});
|
||
if (response.status !== 200) {
|
||
this.logger.error(`\u4E0B\u8F7D\u8D44\u6E90\u5931\u8D25: ${response.status}`);
|
||
this.logger.error(`\u54CD\u5E94\u5185\u5BB9: ${response.text}`);
|
||
return null;
|
||
}
|
||
if ("arrayBuffer" in response && response.arrayBuffer) {
|
||
this.logger.debug(`\u6210\u529F\u83B7\u53D6\u8D44\u6E90\uFF0C\u5927\u5C0F: ${response.arrayBuffer.byteLength} \u5B57\u8282`);
|
||
return response.arrayBuffer;
|
||
} else {
|
||
this.logger.warn("\u54CD\u5E94\u4E2D\u6CA1\u6709 arrayBuffer \u5C5E\u6027");
|
||
return null;
|
||
}
|
||
} catch (error) {
|
||
this.logger.error("\u4E0B\u8F7D\u8D44\u6E90\u65F6\u51FA\u9519:", error);
|
||
return null;
|
||
}
|
||
}
|
||
};
|
||
|
||
// src/services/file-service.ts
|
||
var import_obsidian4 = require("obsidian");
|
||
var FileService = class {
|
||
constructor(vault, syncDirectory, memosService) {
|
||
this.vault = vault;
|
||
this.syncDirectory = syncDirectory;
|
||
this.memosService = memosService;
|
||
this.logger = new Logger("FileService");
|
||
}
|
||
formatDateTime(date, format = "display") {
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||
const day = String(date.getDate()).padStart(2, "0");
|
||
const hours = String(date.getHours()).padStart(2, "0");
|
||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||
const seconds = String(date.getSeconds()).padStart(2, "0");
|
||
if (format === "filename") {
|
||
return `${year}-${month}-${day} ${hours}-${minutes}`;
|
||
}
|
||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||
}
|
||
sanitizeFileName(fileName) {
|
||
let sanitized = fileName.replace(/^[\\/:*?"<>|#\s]+/, "");
|
||
sanitized = sanitized.replace(/\s+/g, " ").replace(/[\\/:*?"<>|#]/g, "").trim();
|
||
return sanitized || "untitled";
|
||
}
|
||
getRelativePath(fromPath, toPath) {
|
||
const fromParts = fromPath.split("/");
|
||
const toParts = toPath.split("/");
|
||
fromParts.pop();
|
||
let i = 0;
|
||
while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
|
||
i++;
|
||
}
|
||
const goBack = fromParts.length - i;
|
||
const relativePath = [
|
||
...Array(goBack).fill(".."),
|
||
...toParts.slice(i)
|
||
].join("/");
|
||
return relativePath;
|
||
}
|
||
isImageFile(filename) {
|
||
const imageExtensions = [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"];
|
||
const ext = filename.toLowerCase().split(".").pop();
|
||
return ext ? imageExtensions.includes(`.${ext}`) : false;
|
||
}
|
||
async ensureDirectoryExists(dirPath) {
|
||
if (!await this.vault.adapter.exists(dirPath)) {
|
||
await this.vault.adapter.mkdir(dirPath);
|
||
}
|
||
}
|
||
getContentPreview(content) {
|
||
let preview = content.replace(/^>\s*\[!.*?\].*$/gm, "").replace(/^>\s.*$/gm, "").replace(/^\s*#\s+/gm, "").replace(/[_*~`]|_{2,}|\*{2,}|~{2,}/g, "").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]*\)/g, "").replace(/\n+/g, " ").trim();
|
||
if (!preview) {
|
||
return "Untitled";
|
||
}
|
||
if (preview.length > 50) {
|
||
preview = `${preview.slice(0, 50)}...`;
|
||
}
|
||
return preview;
|
||
}
|
||
async getMemoFiles() {
|
||
const files = [];
|
||
const processDirectory = async (dirPath) => {
|
||
const items = await this.vault.adapter.list(dirPath);
|
||
for (const file of items.files) {
|
||
if (file.endsWith(".md")) {
|
||
files.push(file);
|
||
}
|
||
}
|
||
for (const dir of items.folders) {
|
||
await processDirectory(dir);
|
||
}
|
||
};
|
||
await processDirectory(this.syncDirectory);
|
||
return files;
|
||
}
|
||
async isMemoExists(memoId) {
|
||
try {
|
||
const files = await this.getMemoFiles();
|
||
for (const file of files) {
|
||
const content = await this.vault.adapter.read(file);
|
||
if (content.includes(`> - ID: ${memoId}`)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
} catch (error) {
|
||
this.logger.error("\u68C0\u67E5 memo \u662F\u5426\u5B58\u5728\u65F6\u51FA\u9519:", error instanceof Error ? error.message : String(error));
|
||
return false;
|
||
}
|
||
}
|
||
async saveMemoToFile(memo) {
|
||
try {
|
||
const exists = await this.isMemoExists(memo.name);
|
||
if (exists) {
|
||
this.logger.debug(`Memo ${memo.name} \u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7`);
|
||
return;
|
||
}
|
||
const date = new Date(memo.createTime);
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||
const yearDir = `${this.syncDirectory}/${year}`;
|
||
const monthDir = `${yearDir}/${month}`;
|
||
await this.ensureDirectoryExists(yearDir);
|
||
await this.ensureDirectoryExists(monthDir);
|
||
const contentPreview = memo.content ? this.getContentPreview(memo.content) : this.sanitizeFileName(memo.name.replace("memos/", ""));
|
||
const timeStr = this.formatDateTime(date, "filename");
|
||
const fileName = this.sanitizeFileName(`${contentPreview} (${timeStr}).md`);
|
||
const filePath = `${monthDir}/${fileName}`;
|
||
let content = memo.content || "";
|
||
content = content.replace(/\#([^\#\s]+)\#/g, "#$1");
|
||
let documentContent = content;
|
||
if (memo.attachments && memo.attachments.length > 0) {
|
||
const images = memo.attachments.filter((r) => this.isImageFile(r.filename));
|
||
const otherFiles = memo.attachments.filter((r) => !this.isImageFile(r.filename));
|
||
if (images.length > 0) {
|
||
documentContent += "\n\n";
|
||
for (const image of images) {
|
||
const resourceData = await this.memosService.downloadResource(image);
|
||
if (resourceData) {
|
||
const resourceDir = `${monthDir}/resources`;
|
||
await this.ensureDirectoryExists(resourceDir);
|
||
const localFilename = `${image.name.split("/").pop()}_${this.sanitizeFileName(image.filename)}`;
|
||
const localPath = `${resourceDir}/${localFilename}`;
|
||
await this.vault.adapter.writeBinary(localPath, resourceData);
|
||
const relativePath = this.getRelativePath(filePath, localPath);
|
||
documentContent += `
|
||
`;
|
||
}
|
||
}
|
||
}
|
||
if (otherFiles.length > 0) {
|
||
documentContent += "\n\n### Attachments\n";
|
||
for (const file of otherFiles) {
|
||
const resourceData = await this.memosService.downloadResource(file);
|
||
if (resourceData) {
|
||
const resourceDir = `${monthDir}/resources`;
|
||
await this.ensureDirectoryExists(resourceDir);
|
||
const localFilename = `${file.name.split("/").pop()}_${this.sanitizeFileName(file.filename)}`;
|
||
const localPath = `${resourceDir}/${localFilename}`;
|
||
await this.vault.adapter.writeBinary(localPath, resourceData);
|
||
const relativePath = this.getRelativePath(filePath, localPath);
|
||
documentContent += `- [${file.filename}](${relativePath})
|
||
`;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
const tags = (memo.content || "").match(/\#([^\#\s]+)(?:\#|\s|$)/g) || [];
|
||
const cleanTags = tags.map((tag) => tag.replace(/^\#|\#$/g, "").trim());
|
||
documentContent += "\n\n---\n";
|
||
documentContent += "> [!note]- Memo Properties\n";
|
||
documentContent += `> - Created: ${this.formatDateTime(new Date(memo.createTime))}
|
||
`;
|
||
documentContent += `> - Updated: ${this.formatDateTime(new Date(memo.updateTime))}
|
||
`;
|
||
documentContent += "> - Type: memo\n";
|
||
if (cleanTags.length > 0) {
|
||
documentContent += `> - Tags: [${cleanTags.join(", ")}]
|
||
`;
|
||
}
|
||
documentContent += `> - ID: ${memo.name}
|
||
`;
|
||
documentContent += `> - Visibility: ${memo.visibility.toLowerCase()}
|
||
`;
|
||
try {
|
||
const exists2 = await this.vault.adapter.exists(filePath);
|
||
if (exists2) {
|
||
const abstractFile = this.vault.getAbstractFileByPath(filePath);
|
||
if (abstractFile instanceof import_obsidian4.TFile) {
|
||
await this.vault.modify(abstractFile, documentContent);
|
||
} else {
|
||
throw new Error("Invalid file type");
|
||
}
|
||
} else {
|
||
await this.vault.create(filePath, documentContent);
|
||
}
|
||
} catch (error) {
|
||
console.error(`Failed to save memo to file: ${filePath}`, error);
|
||
throw new Error(`Failed to save memo: ${error.message}`);
|
||
}
|
||
} catch (error) {
|
||
this.logger.error("\u4FDD\u5B58 memo \u5230\u6587\u4EF6\u65F6\u51FA\u9519:", error instanceof Error ? error.message : String(error));
|
||
throw new Error(`\u4FDD\u5B58 memo \u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
||
}
|
||
}
|
||
};
|
||
|
||
// src/services/content-service.ts
|
||
var ContentService = class {
|
||
constructor(aiService, aiEnabled, enableSummary, enableTags, summaryLanguage, vault, syncDirectory) {
|
||
this.aiService = aiService;
|
||
this.aiEnabled = aiEnabled;
|
||
this.enableSummary = enableSummary;
|
||
this.enableTags = enableTags;
|
||
this.summaryLanguage = summaryLanguage;
|
||
this.vault = vault;
|
||
this.syncDirectory = syncDirectory;
|
||
}
|
||
isContentSuitableForAI(content) {
|
||
const cleanContent = content.replace(/\[([^\]]*)\]\([^)]*\)/g, "").replace(/!\[([^\]]*)\]\([^)]*\)/g, "").replace(/```[\s\S]*?```/g, "").trim();
|
||
return cleanContent.length >= 10;
|
||
}
|
||
async processMemoContent(memo) {
|
||
const { content } = memo;
|
||
const title = this.extractTitle(content);
|
||
const mainContent = title ? content.slice(title.length).trim() : content;
|
||
let processedContent = title ? `# ${title}
|
||
|
||
` : "";
|
||
if (this.aiEnabled && this.isContentSuitableForAI(content)) {
|
||
if (this.enableSummary) {
|
||
const summary = await this.aiService.generateSummary(content, this.summaryLanguage);
|
||
if (summary == null ? void 0 : summary.trim()) {
|
||
processedContent += `> [!abstract]+ \u5185\u5BB9\u6458\u8981
|
||
> ${summary.replace(/\n/g, "\n> ")}
|
||
|
||
`;
|
||
}
|
||
}
|
||
if (this.enableTags) {
|
||
const tags = await this.aiService.generateTags(content);
|
||
if ((tags == null ? void 0 : tags.length) > 0) {
|
||
processedContent += `> [!info]- \u76F8\u5173\u6807\u7B7E
|
||
> ${tags.map((tag) => `#${tag}`).join(" ")}
|
||
|
||
`;
|
||
}
|
||
}
|
||
}
|
||
processedContent += mainContent;
|
||
return processedContent.trim();
|
||
}
|
||
extractTitle(content) {
|
||
const lines = content.split("\n");
|
||
const firstLine = lines[0].trim();
|
||
if (firstLine.startsWith("# ")) {
|
||
return firstLine.slice(2).trim();
|
||
}
|
||
return null;
|
||
}
|
||
async weeklyDigestExists(year, week) {
|
||
const weeklyDigestPath = this.getWeeklyDigestPath(year, week);
|
||
return await this.vault.adapter.exists(weeklyDigestPath);
|
||
}
|
||
getWeeklyDigestPath(year, week) {
|
||
const weeklyDigestDir = `${this.syncDirectory}/${year}/weekly`;
|
||
const fileName = `\u7B2C${week}\u5468\u603B\u7ED3.md`;
|
||
return `${weeklyDigestDir}/${fileName}`;
|
||
}
|
||
async ensureDirectoryExists(dirPath) {
|
||
if (!await this.vault.adapter.exists(dirPath)) {
|
||
await this.vault.adapter.mkdir(dirPath);
|
||
}
|
||
}
|
||
async generateWeeklyDigest(memos) {
|
||
if (!this.aiEnabled) {
|
||
return;
|
||
}
|
||
const suitableMemos = memos.filter((memo) => this.isContentSuitableForAI(memo.content));
|
||
if (suitableMemos.length === 0) {
|
||
return;
|
||
}
|
||
const weekGroups = this.groupMemosByWeek(suitableMemos);
|
||
for (const [weekKey, weekMemos] of Object.entries(weekGroups)) {
|
||
const [year, week] = weekKey.split("-W");
|
||
if (await this.weeklyDigestExists(year, week)) {
|
||
continue;
|
||
}
|
||
const weeklyDigestDir = `${this.syncDirectory}/${year}/weekly`;
|
||
await this.ensureDirectoryExists(weeklyDigestDir);
|
||
const contents = weekMemos.map((memo) => memo.content);
|
||
const digest = await this.aiService.generateWeeklyDigest(contents);
|
||
if (digest == null ? void 0 : digest.trim()) {
|
||
const weeklyContent = this.formatWeeklyDigest(digest, year, week, weekMemos.length);
|
||
const weeklyDigestPath = this.getWeeklyDigestPath(year, week);
|
||
try {
|
||
await this.vault.create(weeklyDigestPath, weeklyContent);
|
||
} catch (error) {
|
||
console.error(`\u751F\u6210\u7B2C ${week} \u5468\u603B\u7ED3\u5931\u8D25:`, error);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
formatWeeklyDigest(digest, year, week, memoCount) {
|
||
const weekRange = this.getWeekDateRange(Number.parseInt(year, 10), Number.parseInt(week, 10));
|
||
return `# \u{1F4C5} \u7B2C ${week} \u5468\u56DE\u987E (${weekRange})
|
||
|
||
## \u{1F31F} \u672C\u5468\u4EAE\u70B9
|
||
|
||
${digest}
|
||
|
||
## \u{1F4CA} \u7EDF\u8BA1\u6570\u636E
|
||
|
||
- \u{1F4DD} \u8BB0\u5F55\u6570\u91CF\uFF1A${memoCount} \u6761
|
||
- \u{1F4C5} \u65F6\u95F4\u8303\u56F4\uFF1A${weekRange}
|
||
|
||
## \u{1F4AA} \u4E0B\u5468\u5C55\u671B
|
||
|
||
> [!quote] \u6FC0\u52B1\u8BED\u5F55
|
||
> \u6BCF\u4E00\u4E2A\u5F53\u4E0B\u90FD\u662F\u672A\u6765\u7684\u8D77\u70B9\uFF0C\u8BA9\u6211\u4EEC\u7EE7\u7EED\u524D\u884C\uFF0C\u521B\u9020\u66F4\u591A\u7CBE\u5F69\uFF01
|
||
|
||
---
|
||
*\u751F\u6210\u65F6\u95F4\uFF1A${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { hour12: false })}*
|
||
|
||
`;
|
||
}
|
||
getWeekDateRange(year, week) {
|
||
const firstDayOfYear = new Date(year, 0, 1);
|
||
const daysToFirstMonday = (8 - firstDayOfYear.getDay()) % 7;
|
||
const firstMonday = new Date(year, 0, 1 + daysToFirstMonday);
|
||
const weekStart = new Date(firstMonday);
|
||
weekStart.setDate(firstMonday.getDate() + (week - 1) * 7);
|
||
const weekEnd = new Date(weekStart);
|
||
weekEnd.setDate(weekStart.getDate() + 6);
|
||
const formatDate = (date) => {
|
||
return `${date.getMonth() + 1}\u6708${date.getDate()}\u65E5`;
|
||
};
|
||
return `${formatDate(weekStart)} - ${formatDate(weekEnd)}`;
|
||
}
|
||
groupMemosByWeek(memos) {
|
||
const groups = {};
|
||
for (const memo of memos) {
|
||
const date = new Date(memo.createTime);
|
||
const year = date.getFullYear();
|
||
const week = this.getWeekNumber(date);
|
||
const key = `${year}-W${week.toString().padStart(2, "0")}`;
|
||
if (!groups[key]) {
|
||
groups[key] = [];
|
||
}
|
||
groups[key].push(memo);
|
||
}
|
||
return groups;
|
||
}
|
||
getWeekNumber(date) {
|
||
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
||
const dayNum = d.getUTCDay() || 7;
|
||
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
||
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
||
return Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
|
||
}
|
||
};
|
||
|
||
// src/services/status-service.ts
|
||
var import_obsidian5 = require("obsidian");
|
||
var StatusService = class {
|
||
constructor(statusBarItem) {
|
||
this.currentStatus = "idle";
|
||
this.syncStartTime = 0;
|
||
this.progressCount = 0;
|
||
this.totalCount = 0;
|
||
this.statusBarItem = statusBarItem;
|
||
this.updateStatusBar();
|
||
}
|
||
updateStatusBar() {
|
||
let icon;
|
||
let text;
|
||
switch (this.currentStatus) {
|
||
case "syncing": {
|
||
icon = "sync";
|
||
const progress = this.totalCount ? ` ${this.progressCount}/${this.totalCount}` : "";
|
||
const elapsed = this.syncStartTime ? ` (${Math.round((Date.now() - this.syncStartTime) / 1e3)}s)` : "";
|
||
text = `\u540C\u6B65\u4E2D${progress}${elapsed}`;
|
||
break;
|
||
}
|
||
case "error": {
|
||
icon = "alert-circle";
|
||
text = "\u540C\u6B65\u5931\u8D25";
|
||
break;
|
||
}
|
||
case "success": {
|
||
icon = "check-circle";
|
||
text = "\u540C\u6B65\u5B8C\u6210";
|
||
break;
|
||
}
|
||
case "warning": {
|
||
icon = "alert-triangle";
|
||
text = "\u8B66\u544A";
|
||
break;
|
||
}
|
||
default: {
|
||
icon = "clock";
|
||
text = "\u7B49\u5F85\u540C\u6B65";
|
||
}
|
||
}
|
||
this.statusBarItem.innerHTML = "";
|
||
const iconSpan = document.createElement("span");
|
||
this.statusBarItem.appendChild(iconSpan);
|
||
(0, import_obsidian5.setIcon)(iconSpan, icon);
|
||
const textSpan = document.createElement("span");
|
||
textSpan.textContent = ` ${text}`;
|
||
this.statusBarItem.appendChild(textSpan);
|
||
}
|
||
startSync(totalItems) {
|
||
this.currentStatus = "syncing";
|
||
this.syncStartTime = Date.now();
|
||
this.progressCount = 0;
|
||
this.totalCount = totalItems;
|
||
this.updateStatusBar();
|
||
new import_obsidian5.Notice("\u5F00\u59CB\u540C\u6B65 Memos");
|
||
}
|
||
updateProgress(current, message) {
|
||
this.progressCount = current;
|
||
this.updateStatusBar();
|
||
if (message) {
|
||
new import_obsidian5.Notice(message);
|
||
}
|
||
}
|
||
setError(error) {
|
||
this.currentStatus = "error";
|
||
this.updateStatusBar();
|
||
new import_obsidian5.Notice(`\u540C\u6B65\u5931\u8D25: ${error}`, 5e3);
|
||
console.error("Sync failed:", error);
|
||
}
|
||
setSuccess(message) {
|
||
this.currentStatus = "success";
|
||
this.updateStatusBar();
|
||
new import_obsidian5.Notice(message);
|
||
setTimeout(() => {
|
||
this.currentStatus = "idle";
|
||
this.updateStatusBar();
|
||
}, 5e3);
|
||
}
|
||
setIdle() {
|
||
this.currentStatus = "idle";
|
||
this.updateStatusBar();
|
||
}
|
||
setWarning(message) {
|
||
this.currentStatus = "warning";
|
||
this.updateStatusBar();
|
||
new import_obsidian5.Notice(message, 5e3);
|
||
console.warn("Warning:", message);
|
||
setTimeout(() => {
|
||
this.currentStatus = "idle";
|
||
this.updateStatusBar();
|
||
}, 5e3);
|
||
}
|
||
};
|
||
|
||
// main.ts
|
||
var MemosSyncPlugin = class extends import_obsidian6.Plugin {
|
||
async onload() {
|
||
await this.loadSettings();
|
||
const statusBarItem = this.addStatusBarItem();
|
||
this.statusService = new StatusService(statusBarItem);
|
||
this.initializeServices();
|
||
this.addSettingTab(new MemosSyncSettingTab(this.app, this));
|
||
this.addRibbonIcon("sync", "Sync Memos", async () => {
|
||
await this.syncMemos();
|
||
});
|
||
if (this.settings.syncFrequency === "auto") {
|
||
this.initializeAutoSync();
|
||
}
|
||
}
|
||
initializeServices() {
|
||
this.memosService = new MemosService(
|
||
this.settings.memosApiUrl,
|
||
this.settings.memosAccessToken,
|
||
this.settings.syncLimit
|
||
);
|
||
let aiService = null;
|
||
if (this.settings.ai.enabled) {
|
||
try {
|
||
const modelName = this.settings.ai.modelName === "custom" ? this.settings.ai.customModelName : this.settings.ai.modelName;
|
||
const apiKey = this.settings.ai.modelType === "ollama" ? this.settings.ai.ollamaBaseUrl : this.settings.ai.apiKey;
|
||
if (this.settings.ai.modelType !== "ollama" && !apiKey) {
|
||
aiService = createDummyAIService();
|
||
this.statusService.setWarning("AI \u670D\u52A1\u9700\u8981\u914D\u7F6E API \u5BC6\u94A5\uFF0C\u8BF7\u5728\u8BBE\u7F6E\u4E2D\u5B8C\u6210\u914D\u7F6E");
|
||
} else {
|
||
aiService = createAIService(
|
||
this.settings.ai.modelType,
|
||
apiKey,
|
||
modelName,
|
||
this.settings.ai.openaiBaseUrl
|
||
);
|
||
}
|
||
} catch (error) {
|
||
console.error("Failed to initialize AI service:", error);
|
||
this.statusService.setWarning("AI \u670D\u52A1\u521D\u59CB\u5316\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u914D\u7F6E");
|
||
aiService = createDummyAIService();
|
||
}
|
||
}
|
||
this.contentService = new ContentService(
|
||
aiService || createDummyAIService(),
|
||
this.settings.ai.enabled && aiService !== null,
|
||
this.settings.ai.intelligentSummary,
|
||
this.settings.ai.autoTags,
|
||
this.settings.ai.summaryLanguage,
|
||
this.app.vault,
|
||
this.settings.syncDirectory
|
||
);
|
||
this.fileService = new FileService(
|
||
this.app.vault,
|
||
this.settings.syncDirectory,
|
||
this.memosService
|
||
);
|
||
}
|
||
async syncMemos() {
|
||
try {
|
||
if (!this.settings.memosApiUrl) {
|
||
throw new Error("\u672A\u914D\u7F6E Memos API URL");
|
||
}
|
||
if (!this.settings.memosAccessToken) {
|
||
throw new Error("\u672A\u914D\u7F6E\u8BBF\u95EE\u4EE4\u724C");
|
||
}
|
||
this.statusService.startSync(0);
|
||
const memos = await this.memosService.fetchAllMemos();
|
||
this.statusService.startSync(memos.length);
|
||
let syncCount = 0;
|
||
for (const memo of memos) {
|
||
const processedContent = await this.contentService.processMemoContent(memo);
|
||
const processedMemo = { ...memo, content: processedContent };
|
||
await this.fileService.saveMemoToFile(processedMemo);
|
||
syncCount++;
|
||
this.statusService.updateProgress(syncCount);
|
||
}
|
||
if (this.settings.ai.enabled && this.settings.ai.weeklyDigest) {
|
||
this.statusService.updateProgress(syncCount, "\u6B63\u5728\u751F\u6210\u6BCF\u5468\u603B\u7ED3...");
|
||
await this.contentService.generateWeeklyDigest(memos);
|
||
}
|
||
this.statusService.setSuccess(`\u540C\u6B65\u5B8C\u6210\uFF0C\u5171\u540C\u6B65 ${syncCount} \u6761\u8BB0\u5F55`);
|
||
} catch (error) {
|
||
console.error("\u540C\u6B65\u5931\u8D25:", error);
|
||
this.statusService.setError(error.message);
|
||
}
|
||
}
|
||
async loadSettings() {
|
||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||
}
|
||
async saveSettings() {
|
||
await this.saveData(this.settings);
|
||
this.initializeServices();
|
||
}
|
||
initializeAutoSync() {
|
||
const interval = this.settings.autoSyncInterval * 60 * 1e3;
|
||
setInterval(() => this.syncMemos(), interval);
|
||
}
|
||
};
|
||
/*! Bundled license information:
|
||
|
||
@google/generative-ai/dist/index.mjs:
|
||
(**
|
||
* @license
|
||
* Copyright 2024 Google LLC
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*)
|
||
|
||
@google/generative-ai/dist/index.mjs:
|
||
(**
|
||
* @license
|
||
* Copyright 2024 Google LLC
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*)
|
||
*/
|