@quilltap/plugin-utils 2.4.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/host-rewrite.d.mts +16 -14
- package/dist/host-rewrite.d.ts +16 -14
- package/dist/host-rewrite.js +2 -59
- package/dist/host-rewrite.js.map +1 -1
- package/dist/host-rewrite.mjs +3 -60
- package/dist/host-rewrite.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +35 -109
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +36 -110
- package/dist/index.mjs.map +1 -1
- package/dist/providers/index.d.mts +16 -0
- package/dist/providers/index.d.ts +16 -0
- package/dist/providers/index.js +32 -49
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/index.mjs +32 -49
- package/dist/providers/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -639,16 +639,21 @@ var OpenAICompatibleProvider = class {
|
|
|
639
639
|
return out;
|
|
640
640
|
}
|
|
641
641
|
/**
|
|
642
|
-
*
|
|
642
|
+
* Build the Chat Completions request body — the ONE build both
|
|
643
|
+
* {@link sendMessage} and {@link streamMessage} call, so the streaming and
|
|
644
|
+
* non-streaming shapes cannot drift apart. Maps Quilltap messages to the
|
|
645
|
+
* OpenAI wire format (tool results and assistant tool calls included),
|
|
646
|
+
* applies {@link applySystemMessagePolicy}, assembles the body literal, and
|
|
647
|
+
* finishes with {@link applyProfileParams}.
|
|
643
648
|
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
649
|
+
* Subclasses that keep the base class's send/stream loops can override this
|
|
650
|
+
* to reshape the body in one place.
|
|
651
|
+
*
|
|
652
|
+
* @param params - LLM parameters for the request
|
|
653
|
+
* @param stream - Whether the body is for a streaming request; adds
|
|
654
|
+
* `stream: true` and `stream_options: { include_usage: true }`
|
|
647
655
|
*/
|
|
648
|
-
|
|
649
|
-
this.validateApiKeyRequirement(apiKey);
|
|
650
|
-
const attachmentResults = this.collectAttachmentFailures(params);
|
|
651
|
-
const client = this.createClient(apiKey);
|
|
656
|
+
buildRequestBody(params, stream) {
|
|
652
657
|
const mappedMessages = params.messages.filter((m) => {
|
|
653
658
|
if (m.role === "tool" && !m.toolCallId) return false;
|
|
654
659
|
return true;
|
|
@@ -684,12 +689,30 @@ var OpenAICompatibleProvider = class {
|
|
|
684
689
|
max_tokens: params.maxTokens ?? 4096,
|
|
685
690
|
top_p: params.topP ?? 1,
|
|
686
691
|
stop: params.stop,
|
|
692
|
+
// Spread here — not appended after the literal — so the streaming keys
|
|
693
|
+
// keep their historical position between `stop` and `user` and the
|
|
694
|
+
// serialized body stays byte-identical.
|
|
695
|
+
...stream ? { stream: true, stream_options: { include_usage: true } } : {},
|
|
687
696
|
...params.cacheKey ? { user: params.cacheKey } : {},
|
|
688
697
|
// Tools arrive only once the runtime gate (the profile's "Allow tool
|
|
689
698
|
// use") has passed, so no separate guard is needed here.
|
|
690
699
|
...params.tools && params.tools.length > 0 ? { tools: params.tools, tool_choice: params.toolChoice ?? "auto" } : {}
|
|
691
700
|
};
|
|
692
701
|
this.applyProfileParams(body, params);
|
|
702
|
+
return body;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Sends a message and returns the complete response.
|
|
706
|
+
*
|
|
707
|
+
* @param params - LLM parameters including messages, model, and settings
|
|
708
|
+
* @param apiKey - API key for authentication
|
|
709
|
+
* @returns Complete LLM response with content and usage statistics
|
|
710
|
+
*/
|
|
711
|
+
async sendMessage(params, apiKey) {
|
|
712
|
+
this.validateApiKeyRequirement(apiKey);
|
|
713
|
+
const attachmentResults = this.collectAttachmentFailures(params);
|
|
714
|
+
const client = this.createClient(apiKey);
|
|
715
|
+
const body = this.buildRequestBody(params, false);
|
|
693
716
|
try {
|
|
694
717
|
const response = await client.chat.completions.create(
|
|
695
718
|
body,
|
|
@@ -729,47 +752,7 @@ var OpenAICompatibleProvider = class {
|
|
|
729
752
|
this.validateApiKeyRequirement(apiKey);
|
|
730
753
|
const attachmentResults = this.collectAttachmentFailures(params);
|
|
731
754
|
const client = this.createClient(apiKey);
|
|
732
|
-
const
|
|
733
|
-
if (m.role === "tool" && !m.toolCallId) return false;
|
|
734
|
-
return true;
|
|
735
|
-
}).map((m) => {
|
|
736
|
-
if (m.role === "tool" && m.toolCallId) {
|
|
737
|
-
return {
|
|
738
|
-
role: "tool",
|
|
739
|
-
tool_call_id: m.toolCallId,
|
|
740
|
-
content: m.content
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
|
|
744
|
-
return {
|
|
745
|
-
role: "assistant",
|
|
746
|
-
content: m.content || null,
|
|
747
|
-
tool_calls: m.toolCalls.map((tc) => ({
|
|
748
|
-
id: tc.id,
|
|
749
|
-
type: tc.type,
|
|
750
|
-
function: tc.function
|
|
751
|
-
}))
|
|
752
|
-
};
|
|
753
|
-
}
|
|
754
|
-
return {
|
|
755
|
-
role: m.role,
|
|
756
|
-
content: m.content
|
|
757
|
-
};
|
|
758
|
-
});
|
|
759
|
-
const messages = this.applySystemMessagePolicy(mappedMessages);
|
|
760
|
-
const body = {
|
|
761
|
-
model: params.model,
|
|
762
|
-
messages,
|
|
763
|
-
temperature: params.temperature ?? 0.7,
|
|
764
|
-
max_tokens: params.maxTokens ?? 4096,
|
|
765
|
-
top_p: params.topP ?? 1,
|
|
766
|
-
stop: params.stop,
|
|
767
|
-
stream: true,
|
|
768
|
-
stream_options: { include_usage: true },
|
|
769
|
-
...params.cacheKey ? { user: params.cacheKey } : {},
|
|
770
|
-
...params.tools && params.tools.length > 0 ? { tools: params.tools, tool_choice: params.toolChoice ?? "auto" } : {}
|
|
771
|
-
};
|
|
772
|
-
this.applyProfileParams(body, params);
|
|
755
|
+
const body = this.buildRequestBody(params, true);
|
|
773
756
|
try {
|
|
774
757
|
const stream = await client.chat.completions.create(
|
|
775
758
|
body,
|
|
@@ -1015,9 +998,6 @@ var LOCALHOST_HOSTS = /* @__PURE__ */ new Set([
|
|
|
1015
998
|
]);
|
|
1016
999
|
var cachedGatewayHost;
|
|
1017
1000
|
var rewriteLogger = createPluginLogger("host-rewrite");
|
|
1018
|
-
function isLimaEnvironment() {
|
|
1019
|
-
return process.env.LIMA_CONTAINER === "true";
|
|
1020
|
-
}
|
|
1021
1001
|
function isDockerEnvironment() {
|
|
1022
1002
|
if (process.env.DOCKER_CONTAINER === "true") {
|
|
1023
1003
|
return true;
|
|
@@ -1035,7 +1015,7 @@ function isDockerEnvironment() {
|
|
|
1035
1015
|
return false;
|
|
1036
1016
|
}
|
|
1037
1017
|
function isVMEnvironment() {
|
|
1038
|
-
return isDockerEnvironment() ||
|
|
1018
|
+
return isDockerEnvironment() || !!process.env.QUILLTAP_HOST_IP;
|
|
1039
1019
|
}
|
|
1040
1020
|
function resolveHostGateway() {
|
|
1041
1021
|
if (cachedGatewayHost !== void 0) {
|
|
@@ -1047,65 +1027,11 @@ function resolveHostGateway() {
|
|
|
1047
1027
|
cachedGatewayHost = envIP;
|
|
1048
1028
|
return cachedGatewayHost;
|
|
1049
1029
|
}
|
|
1050
|
-
if (isDockerEnvironment()
|
|
1030
|
+
if (isDockerEnvironment()) {
|
|
1051
1031
|
rewriteLogger.info("Docker environment detected \u2014 using host.docker.internal as gateway hostname");
|
|
1052
1032
|
cachedGatewayHost = "host.docker.internal";
|
|
1053
1033
|
return cachedGatewayHost;
|
|
1054
1034
|
}
|
|
1055
|
-
try {
|
|
1056
|
-
if ((0, import_node_fs.existsSync)("/proc/sys/fs/binfmt_misc/WSLInterop")) {
|
|
1057
|
-
const resolv = (0, import_node_fs.readFileSync)("/etc/resolv.conf", "utf-8");
|
|
1058
|
-
for (const line of resolv.split("\n")) {
|
|
1059
|
-
const trimmed = line.trim();
|
|
1060
|
-
if (trimmed.startsWith("#") || trimmed === "") continue;
|
|
1061
|
-
const match = trimmed.match(/^nameserver\s+(\S+)/);
|
|
1062
|
-
if (match) {
|
|
1063
|
-
const ip = match[1];
|
|
1064
|
-
rewriteLogger.info("WSL2 host IP from /etc/resolv.conf nameserver", { ip });
|
|
1065
|
-
cachedGatewayHost = ip;
|
|
1066
|
-
return cachedGatewayHost;
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
} catch {
|
|
1071
|
-
rewriteLogger.debug("Could not detect WSL2 or read /etc/resolv.conf");
|
|
1072
|
-
}
|
|
1073
|
-
try {
|
|
1074
|
-
const routeTable = (0, import_node_fs.readFileSync)("/proc/net/route", "utf-8");
|
|
1075
|
-
for (const line of routeTable.split("\n").slice(1)) {
|
|
1076
|
-
const fields = line.trim().split(" ");
|
|
1077
|
-
if (fields.length >= 3 && fields[1] === "00000000") {
|
|
1078
|
-
const hexGateway = fields[2];
|
|
1079
|
-
const ip = [
|
|
1080
|
-
parseInt(hexGateway.substring(6, 8), 16),
|
|
1081
|
-
parseInt(hexGateway.substring(4, 6), 16),
|
|
1082
|
-
parseInt(hexGateway.substring(2, 4), 16),
|
|
1083
|
-
parseInt(hexGateway.substring(0, 2), 16)
|
|
1084
|
-
].join(".");
|
|
1085
|
-
rewriteLogger.info("Host gateway IP from /proc/net/route", { ip });
|
|
1086
|
-
cachedGatewayHost = ip;
|
|
1087
|
-
return cachedGatewayHost;
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
} catch {
|
|
1091
|
-
rewriteLogger.debug("Could not read /proc/net/route for default gateway lookup");
|
|
1092
|
-
}
|
|
1093
|
-
try {
|
|
1094
|
-
const hosts = (0, import_node_fs.readFileSync)("/etc/hosts", "utf-8");
|
|
1095
|
-
for (const line of hosts.split("\n")) {
|
|
1096
|
-
const trimmed = line.trim();
|
|
1097
|
-
if (trimmed.startsWith("#") || trimmed === "") continue;
|
|
1098
|
-
const parts = trimmed.split(/\s+/);
|
|
1099
|
-
if (parts.length >= 2 && parts.slice(1).includes("host.docker.internal")) {
|
|
1100
|
-
const ip = parts[0];
|
|
1101
|
-
rewriteLogger.info("Host gateway IP from /etc/hosts (host.docker.internal)", { ip });
|
|
1102
|
-
cachedGatewayHost = ip;
|
|
1103
|
-
return cachedGatewayHost;
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
} catch {
|
|
1107
|
-
rewriteLogger.debug("Could not read /etc/hosts for host.docker.internal lookup");
|
|
1108
|
-
}
|
|
1109
1035
|
rewriteLogger.warn("Could not resolve host gateway \u2014 localhost URLs will not be rewritten");
|
|
1110
1036
|
cachedGatewayHost = null;
|
|
1111
1037
|
return cachedGatewayHost;
|
|
@@ -1138,7 +1064,7 @@ function rewriteLocalhostUrl(url) {
|
|
|
1138
1064
|
}
|
|
1139
1065
|
|
|
1140
1066
|
// src/version.generated.ts
|
|
1141
|
-
var PLUGIN_UTILS_VERSION = "2.
|
|
1067
|
+
var PLUGIN_UTILS_VERSION = "2.6.0";
|
|
1142
1068
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1143
1069
|
0 && (module.exports = {
|
|
1144
1070
|
BUILTIN_TOOL_NAMES,
|