@openhoo/hoopilot 0.7.3 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +81 -30
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +144 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +144 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -571,6 +571,12 @@ function isLogLevel(value) {
|
|
|
571
571
|
|
|
572
572
|
// src/openai.ts
|
|
573
573
|
var DEFAULT_MODEL = "gpt-4.1";
|
|
574
|
+
var OpenAICompatibilityError = class extends Error {
|
|
575
|
+
constructor(message) {
|
|
576
|
+
super(message);
|
|
577
|
+
this.name = "OpenAICompatibilityError";
|
|
578
|
+
}
|
|
579
|
+
};
|
|
574
580
|
function normalizeChatCompletionRequest(request) {
|
|
575
581
|
return removeUndefined({
|
|
576
582
|
...request,
|
|
@@ -578,13 +584,22 @@ function normalizeChatCompletionRequest(request) {
|
|
|
578
584
|
});
|
|
579
585
|
}
|
|
580
586
|
function completionsRequestToChatCompletion(request) {
|
|
587
|
+
assertSupportedLegacyCompletionRequest(request);
|
|
581
588
|
return removeUndefined({
|
|
589
|
+
frequency_penalty: request.frequency_penalty,
|
|
590
|
+
logit_bias: request.logit_bias,
|
|
582
591
|
max_tokens: request.max_tokens,
|
|
583
|
-
messages: [{ content:
|
|
592
|
+
messages: [{ content: legacyPromptToText(request.prompt), role: "user" }],
|
|
584
593
|
model: normalizeRequestedModel(request.model),
|
|
594
|
+
n: request.n,
|
|
595
|
+
presence_penalty: request.presence_penalty,
|
|
596
|
+
seed: request.seed,
|
|
597
|
+
stop: request.stop,
|
|
585
598
|
stream: request.stream === true,
|
|
599
|
+
stream_options: request.stream_options,
|
|
586
600
|
temperature: request.temperature,
|
|
587
|
-
top_p: request.top_p
|
|
601
|
+
top_p: request.top_p,
|
|
602
|
+
user: request.user
|
|
588
603
|
});
|
|
589
604
|
}
|
|
590
605
|
function normalizeRequestedModel(model) {
|
|
@@ -592,21 +607,21 @@ function normalizeRequestedModel(model) {
|
|
|
592
607
|
return requested || DEFAULT_MODEL;
|
|
593
608
|
}
|
|
594
609
|
function chatCompletionToCompletion(completion) {
|
|
595
|
-
const choice = firstChoice(completion);
|
|
596
|
-
const message = asRecord(choice.message);
|
|
597
610
|
return removeUndefined({
|
|
598
|
-
choices:
|
|
599
|
-
|
|
611
|
+
choices: completionChoices(completion).map((choice, index) => {
|
|
612
|
+
const message = asRecord(choice.message);
|
|
613
|
+
return {
|
|
600
614
|
finish_reason: choice.finish_reason ?? "stop",
|
|
601
|
-
index:
|
|
602
|
-
logprobs: null,
|
|
603
|
-
text: contentToText(message.content)
|
|
604
|
-
}
|
|
605
|
-
|
|
615
|
+
index: typeof choice.index === "number" ? choice.index : index,
|
|
616
|
+
logprobs: choice.logprobs ?? null,
|
|
617
|
+
text: contentToText(choice.text) || contentToText(message.content)
|
|
618
|
+
};
|
|
619
|
+
}),
|
|
606
620
|
created: completion.created ?? epochSeconds(),
|
|
607
621
|
id: completion.id ?? `cmpl_${randomId()}`,
|
|
608
622
|
model: completion.model ?? DEFAULT_MODEL,
|
|
609
623
|
object: "text_completion",
|
|
624
|
+
system_fingerprint: completion.system_fingerprint,
|
|
610
625
|
usage: completion.usage
|
|
611
626
|
});
|
|
612
627
|
}
|
|
@@ -679,11 +694,38 @@ function fallbackModels() {
|
|
|
679
694
|
}
|
|
680
695
|
];
|
|
681
696
|
}
|
|
682
|
-
function
|
|
683
|
-
if (
|
|
684
|
-
return prompt
|
|
697
|
+
function legacyPromptToText(prompt) {
|
|
698
|
+
if (typeof prompt === "string") {
|
|
699
|
+
return prompt;
|
|
700
|
+
}
|
|
701
|
+
if (Array.isArray(prompt) && prompt.length === 1 && typeof prompt[0] === "string") {
|
|
702
|
+
return prompt[0];
|
|
703
|
+
}
|
|
704
|
+
throw new OpenAICompatibilityError(
|
|
705
|
+
"Hoopilot legacy completions compatibility supports exactly one string prompt per request."
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
function assertSupportedLegacyCompletionRequest(request) {
|
|
709
|
+
if (request.echo === true) {
|
|
710
|
+
throw new OpenAICompatibilityError(
|
|
711
|
+
"Hoopilot legacy completions compatibility does not support echo=true."
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
if (typeof request.best_of === "number" && request.best_of > 1) {
|
|
715
|
+
throw new OpenAICompatibilityError(
|
|
716
|
+
"Hoopilot legacy completions compatibility does not support best_of greater than 1."
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
if (typeof request.logprobs === "number" && request.logprobs > 0) {
|
|
720
|
+
throw new OpenAICompatibilityError(
|
|
721
|
+
"Hoopilot legacy completions compatibility does not support legacy logprobs."
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
if (contentToText(request.suffix)) {
|
|
725
|
+
throw new OpenAICompatibilityError(
|
|
726
|
+
"Hoopilot legacy completions compatibility does not support suffix."
|
|
727
|
+
);
|
|
685
728
|
}
|
|
686
|
-
return contentToText(prompt);
|
|
687
729
|
}
|
|
688
730
|
function contentToText(content) {
|
|
689
731
|
if (typeof content === "string") {
|
|
@@ -741,9 +783,9 @@ function firstNumber(...values) {
|
|
|
741
783
|
}
|
|
742
784
|
return void 0;
|
|
743
785
|
}
|
|
744
|
-
function
|
|
786
|
+
function completionChoices(completion) {
|
|
745
787
|
const choices = Array.isArray(completion.choices) ? completion.choices : [];
|
|
746
|
-
return asRecord(
|
|
788
|
+
return choices.map((choice) => asRecord(choice));
|
|
747
789
|
}
|
|
748
790
|
function processCompletionSseBlock(block, enqueue, markTerminal) {
|
|
749
791
|
let event = "message";
|
|
@@ -775,25 +817,28 @@ function processCompletionSseBlock(block, enqueue, markTerminal) {
|
|
|
775
817
|
enqueue({ error });
|
|
776
818
|
return;
|
|
777
819
|
}
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
820
|
+
const choices = completionChoices(parsed).map((choice, index) => {
|
|
821
|
+
const delta = asRecord(choice.delta);
|
|
822
|
+
const text = contentToText(delta.content);
|
|
823
|
+
const finishReason = choice.finish_reason ?? null;
|
|
824
|
+
if (!text && finishReason === null) {
|
|
825
|
+
return void 0;
|
|
826
|
+
}
|
|
827
|
+
return {
|
|
828
|
+
finish_reason: finishReason,
|
|
829
|
+
index: typeof choice.index === "number" ? choice.index : index,
|
|
830
|
+
logprobs: choice.logprobs ?? null,
|
|
831
|
+
text
|
|
832
|
+
};
|
|
833
|
+
}).filter((choice) => choice !== void 0);
|
|
782
834
|
const usage = asRecord(parsed.usage);
|
|
783
835
|
const hasUsage = Object.keys(usage).length > 0;
|
|
784
|
-
if (
|
|
836
|
+
if (choices.length === 0 && !hasUsage) {
|
|
785
837
|
return;
|
|
786
838
|
}
|
|
787
839
|
enqueue(
|
|
788
840
|
removeUndefined({
|
|
789
|
-
choices
|
|
790
|
-
{
|
|
791
|
-
finish_reason: finishReason,
|
|
792
|
-
index: typeof choice.index === "number" ? choice.index : 0,
|
|
793
|
-
logprobs: null,
|
|
794
|
-
text
|
|
795
|
-
}
|
|
796
|
-
] : [],
|
|
841
|
+
choices,
|
|
797
842
|
created: typeof parsed.created === "number" ? parsed.created : epochSeconds(),
|
|
798
843
|
id: contentToText(parsed.id) || `cmpl_${randomId()}`,
|
|
799
844
|
model: contentToText(parsed.model) || DEFAULT_MODEL,
|
|
@@ -1312,6 +1357,12 @@ function createHoopilotHandler(options = {}) {
|
|
|
1312
1357
|
"request body was invalid json"
|
|
1313
1358
|
);
|
|
1314
1359
|
return finish(jsonError(400, "invalid_request_error", message));
|
|
1360
|
+
} else if (error instanceof OpenAICompatibilityError) {
|
|
1361
|
+
requestLogger.warn(
|
|
1362
|
+
{ err: errorDetails(error), event: "http.request.failed" },
|
|
1363
|
+
"request body used unsupported OpenAI compatibility fields"
|
|
1364
|
+
);
|
|
1365
|
+
return finish(jsonError(400, "invalid_request_error", message));
|
|
1315
1366
|
} else if (error instanceof RequestBodyTooLargeError) {
|
|
1316
1367
|
requestLogger.warn(
|
|
1317
1368
|
{ err: errorDetails(error), event: "http.request.failed" },
|