ravendb
Version:
RavenDB client for Node.js
150 lines • 5.97 kB
JavaScript
import { Readable } from "node:stream";
import { createInterface } from "node:readline";
import { RavenCommand } from "../../../../Http/RavenCommand.js";
import { RaftIdGenerator } from "../../../../Utility/RaftIdGenerator.js";
import { throwError } from "../../../../Exceptions/index.js";
import { JsonSerializer } from "../../../../Mapping/Json/Serializer.js";
import { ObjectUtil } from "../../../../Utility/ObjectUtil.js";
import { StringUtil } from "../../../../Utility/StringUtil.js";
export class RunConversationOperation {
_agentId;
_conversationId;
_userPrompt;
_actionResponses;
_options;
_changeVector;
_streamPropertyPath;
_streamCallback;
constructor(agentId, conversationId, userPrompt, actionResponses, options, changeVector, streamPropertyPath, streamCallback) {
if (StringUtil.isNullOrEmpty(agentId)) {
throwError("InvalidArgumentException", "agentId cannot be null or empty.");
}
if (StringUtil.isNullOrEmpty(conversationId)) {
throwError("InvalidArgumentException", "conversationId cannot be null or empty.");
}
// Both streamPropertyPath and streamCallback must be specified together or neither
if ((streamPropertyPath != null) !== (streamCallback != null)) {
throwError("InvalidOperationException", "Both streamPropertyPath and streamCallback must be specified together or neither.");
}
this._agentId = agentId;
this._conversationId = conversationId;
this._userPrompt = userPrompt;
this._actionResponses = actionResponses;
this._options = options;
this._changeVector = changeVector;
this._streamPropertyPath = streamPropertyPath;
this._streamCallback = streamCallback;
}
get resultType() {
return "CommandResult";
}
getCommand(conventions) {
return new RunConversationCommand(this._conversationId, this._agentId, this._userPrompt, this._actionResponses, this._options, this._changeVector, conventions, this._streamPropertyPath, this._streamCallback);
}
}
class RunConversationCommand extends RavenCommand {
_conversationId;
_agentId;
_prompt;
_actionResponses;
_options;
_changeVector;
_streamPropertyPath;
_streamCallback;
_raftId;
constructor(conversationId, agentId, prompt, actionResponses, options, changeVector, conventions, streamPropertyPath, streamCallback) {
super();
this._conversationId = conversationId;
this._agentId = agentId;
this._prompt = prompt;
this._actionResponses = actionResponses;
this._options = options;
this._changeVector = changeVector;
this._streamPropertyPath = streamPropertyPath;
this._streamCallback = streamCallback;
// When streaming is enabled, we need to handle raw response
if (this._streamPropertyPath && this._streamCallback) {
this._responseType = "Raw";
}
if (this._conversationId && this._conversationId.endsWith("|")) {
this._raftId = RaftIdGenerator.newId();
}
}
get isReadRequest() {
return false;
}
getRaftUniqueRequestId() {
return this._raftId;
}
createRequest(node) {
const uriParams = new URLSearchParams({
conversationId: this._conversationId,
agentId: this._agentId,
});
if (this._changeVector) {
uriParams.append("changeVector", this._changeVector);
}
if (this._streamPropertyPath) {
uriParams.append("streaming", "true");
uriParams.append("streamPropertyPath", this._streamPropertyPath);
}
const uri = `${node.url}/databases/${node.database}/ai/agent?${uriParams}`;
const bodyObj = {
ActionResponses: this._actionResponses,
UserPrompt: this._prompt,
CreationOptions: this._options ?? {}
};
const headers = this._headers().typeAppJson().build();
// Serialize properties to PascalCase, except "parameters" in CreationOptions, which must keep user-provided, case-sensitive keys unchanged.
const serialized = ObjectUtil.transformObjectKeys(bodyObj, {
defaultTransform: ObjectUtil.pascalCase,
ignorePaths: [
new RegExp("^CreationOptions\\.Parameters\\..*$")
]
});
return {
method: "POST",
uri,
headers,
body: JsonSerializer.getDefault().serialize(serialized)
};
}
async setResponseAsync(bodyStream, fromCache) {
if (!bodyStream) {
this._throwInvalidResponse();
}
if (this._streamPropertyPath && this._streamCallback) {
return await this._processStreamingResponse(bodyStream);
}
return await this._parseResponseDefaultAsync(bodyStream);
}
async _processStreamingResponse(bodyStream) {
const rl = createInterface({
input: bodyStream,
crlfDelay: Infinity
});
for await (const line of rl) {
if (!line || line.trim().length === 0) {
continue;
}
if (line.startsWith("{")) {
const jsonStream = Readable.from([line]);
let body = null;
this.result = await this._defaultPipeline(_ => body = _).process(jsonStream);
return body;
}
try {
const unescaped = JSON.parse(line);
await this._streamCallback(unescaped);
}
catch (err) {
await this._streamCallback(line);
}
}
if (!this.result) {
throwError("InvalidOperationException", "No final result received in streaming response");
}
return null;
}
}
//# sourceMappingURL=RunConversationOperation.js.map