@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.mjs
CHANGED
|
@@ -562,16 +562,21 @@ var OpenAICompatibleProvider = class {
|
|
|
562
562
|
return out;
|
|
563
563
|
}
|
|
564
564
|
/**
|
|
565
|
-
*
|
|
565
|
+
* Build the Chat Completions request body — the ONE build both
|
|
566
|
+
* {@link sendMessage} and {@link streamMessage} call, so the streaming and
|
|
567
|
+
* non-streaming shapes cannot drift apart. Maps Quilltap messages to the
|
|
568
|
+
* OpenAI wire format (tool results and assistant tool calls included),
|
|
569
|
+
* applies {@link applySystemMessagePolicy}, assembles the body literal, and
|
|
570
|
+
* finishes with {@link applyProfileParams}.
|
|
566
571
|
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
572
|
+
* Subclasses that keep the base class's send/stream loops can override this
|
|
573
|
+
* to reshape the body in one place.
|
|
574
|
+
*
|
|
575
|
+
* @param params - LLM parameters for the request
|
|
576
|
+
* @param stream - Whether the body is for a streaming request; adds
|
|
577
|
+
* `stream: true` and `stream_options: { include_usage: true }`
|
|
570
578
|
*/
|
|
571
|
-
|
|
572
|
-
this.validateApiKeyRequirement(apiKey);
|
|
573
|
-
const attachmentResults = this.collectAttachmentFailures(params);
|
|
574
|
-
const client = this.createClient(apiKey);
|
|
579
|
+
buildRequestBody(params, stream) {
|
|
575
580
|
const mappedMessages = params.messages.filter((m) => {
|
|
576
581
|
if (m.role === "tool" && !m.toolCallId) return false;
|
|
577
582
|
return true;
|
|
@@ -607,12 +612,30 @@ var OpenAICompatibleProvider = class {
|
|
|
607
612
|
max_tokens: params.maxTokens ?? 4096,
|
|
608
613
|
top_p: params.topP ?? 1,
|
|
609
614
|
stop: params.stop,
|
|
615
|
+
// Spread here — not appended after the literal — so the streaming keys
|
|
616
|
+
// keep their historical position between `stop` and `user` and the
|
|
617
|
+
// serialized body stays byte-identical.
|
|
618
|
+
...stream ? { stream: true, stream_options: { include_usage: true } } : {},
|
|
610
619
|
...params.cacheKey ? { user: params.cacheKey } : {},
|
|
611
620
|
// Tools arrive only once the runtime gate (the profile's "Allow tool
|
|
612
621
|
// use") has passed, so no separate guard is needed here.
|
|
613
622
|
...params.tools && params.tools.length > 0 ? { tools: params.tools, tool_choice: params.toolChoice ?? "auto" } : {}
|
|
614
623
|
};
|
|
615
624
|
this.applyProfileParams(body, params);
|
|
625
|
+
return body;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Sends a message and returns the complete response.
|
|
629
|
+
*
|
|
630
|
+
* @param params - LLM parameters including messages, model, and settings
|
|
631
|
+
* @param apiKey - API key for authentication
|
|
632
|
+
* @returns Complete LLM response with content and usage statistics
|
|
633
|
+
*/
|
|
634
|
+
async sendMessage(params, apiKey) {
|
|
635
|
+
this.validateApiKeyRequirement(apiKey);
|
|
636
|
+
const attachmentResults = this.collectAttachmentFailures(params);
|
|
637
|
+
const client = this.createClient(apiKey);
|
|
638
|
+
const body = this.buildRequestBody(params, false);
|
|
616
639
|
try {
|
|
617
640
|
const response = await client.chat.completions.create(
|
|
618
641
|
body,
|
|
@@ -652,47 +675,7 @@ var OpenAICompatibleProvider = class {
|
|
|
652
675
|
this.validateApiKeyRequirement(apiKey);
|
|
653
676
|
const attachmentResults = this.collectAttachmentFailures(params);
|
|
654
677
|
const client = this.createClient(apiKey);
|
|
655
|
-
const
|
|
656
|
-
if (m.role === "tool" && !m.toolCallId) return false;
|
|
657
|
-
return true;
|
|
658
|
-
}).map((m) => {
|
|
659
|
-
if (m.role === "tool" && m.toolCallId) {
|
|
660
|
-
return {
|
|
661
|
-
role: "tool",
|
|
662
|
-
tool_call_id: m.toolCallId,
|
|
663
|
-
content: m.content
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
|
|
667
|
-
return {
|
|
668
|
-
role: "assistant",
|
|
669
|
-
content: m.content || null,
|
|
670
|
-
tool_calls: m.toolCalls.map((tc) => ({
|
|
671
|
-
id: tc.id,
|
|
672
|
-
type: tc.type,
|
|
673
|
-
function: tc.function
|
|
674
|
-
}))
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
return {
|
|
678
|
-
role: m.role,
|
|
679
|
-
content: m.content
|
|
680
|
-
};
|
|
681
|
-
});
|
|
682
|
-
const messages = this.applySystemMessagePolicy(mappedMessages);
|
|
683
|
-
const body = {
|
|
684
|
-
model: params.model,
|
|
685
|
-
messages,
|
|
686
|
-
temperature: params.temperature ?? 0.7,
|
|
687
|
-
max_tokens: params.maxTokens ?? 4096,
|
|
688
|
-
top_p: params.topP ?? 1,
|
|
689
|
-
stop: params.stop,
|
|
690
|
-
stream: true,
|
|
691
|
-
stream_options: { include_usage: true },
|
|
692
|
-
...params.cacheKey ? { user: params.cacheKey } : {},
|
|
693
|
-
...params.tools && params.tools.length > 0 ? { tools: params.tools, tool_choice: params.toolChoice ?? "auto" } : {}
|
|
694
|
-
};
|
|
695
|
-
this.applyProfileParams(body, params);
|
|
678
|
+
const body = this.buildRequestBody(params, true);
|
|
696
679
|
try {
|
|
697
680
|
const stream = await client.chat.completions.create(
|
|
698
681
|
body,
|
|
@@ -929,7 +912,7 @@ function getBuiltinToolNames() {
|
|
|
929
912
|
}
|
|
930
913
|
|
|
931
914
|
// src/host-rewrite.ts
|
|
932
|
-
import {
|
|
915
|
+
import { existsSync, statSync } from "fs";
|
|
933
916
|
var LOCALHOST_HOSTS = /* @__PURE__ */ new Set([
|
|
934
917
|
"localhost",
|
|
935
918
|
"127.0.0.1",
|
|
@@ -938,9 +921,6 @@ var LOCALHOST_HOSTS = /* @__PURE__ */ new Set([
|
|
|
938
921
|
]);
|
|
939
922
|
var cachedGatewayHost;
|
|
940
923
|
var rewriteLogger = createPluginLogger("host-rewrite");
|
|
941
|
-
function isLimaEnvironment() {
|
|
942
|
-
return process.env.LIMA_CONTAINER === "true";
|
|
943
|
-
}
|
|
944
924
|
function isDockerEnvironment() {
|
|
945
925
|
if (process.env.DOCKER_CONTAINER === "true") {
|
|
946
926
|
return true;
|
|
@@ -958,7 +938,7 @@ function isDockerEnvironment() {
|
|
|
958
938
|
return false;
|
|
959
939
|
}
|
|
960
940
|
function isVMEnvironment() {
|
|
961
|
-
return isDockerEnvironment() ||
|
|
941
|
+
return isDockerEnvironment() || !!process.env.QUILLTAP_HOST_IP;
|
|
962
942
|
}
|
|
963
943
|
function resolveHostGateway() {
|
|
964
944
|
if (cachedGatewayHost !== void 0) {
|
|
@@ -970,65 +950,11 @@ function resolveHostGateway() {
|
|
|
970
950
|
cachedGatewayHost = envIP;
|
|
971
951
|
return cachedGatewayHost;
|
|
972
952
|
}
|
|
973
|
-
if (isDockerEnvironment()
|
|
953
|
+
if (isDockerEnvironment()) {
|
|
974
954
|
rewriteLogger.info("Docker environment detected \u2014 using host.docker.internal as gateway hostname");
|
|
975
955
|
cachedGatewayHost = "host.docker.internal";
|
|
976
956
|
return cachedGatewayHost;
|
|
977
957
|
}
|
|
978
|
-
try {
|
|
979
|
-
if (existsSync("/proc/sys/fs/binfmt_misc/WSLInterop")) {
|
|
980
|
-
const resolv = readFileSync("/etc/resolv.conf", "utf-8");
|
|
981
|
-
for (const line of resolv.split("\n")) {
|
|
982
|
-
const trimmed = line.trim();
|
|
983
|
-
if (trimmed.startsWith("#") || trimmed === "") continue;
|
|
984
|
-
const match = trimmed.match(/^nameserver\s+(\S+)/);
|
|
985
|
-
if (match) {
|
|
986
|
-
const ip = match[1];
|
|
987
|
-
rewriteLogger.info("WSL2 host IP from /etc/resolv.conf nameserver", { ip });
|
|
988
|
-
cachedGatewayHost = ip;
|
|
989
|
-
return cachedGatewayHost;
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
} catch {
|
|
994
|
-
rewriteLogger.debug("Could not detect WSL2 or read /etc/resolv.conf");
|
|
995
|
-
}
|
|
996
|
-
try {
|
|
997
|
-
const routeTable = readFileSync("/proc/net/route", "utf-8");
|
|
998
|
-
for (const line of routeTable.split("\n").slice(1)) {
|
|
999
|
-
const fields = line.trim().split(" ");
|
|
1000
|
-
if (fields.length >= 3 && fields[1] === "00000000") {
|
|
1001
|
-
const hexGateway = fields[2];
|
|
1002
|
-
const ip = [
|
|
1003
|
-
parseInt(hexGateway.substring(6, 8), 16),
|
|
1004
|
-
parseInt(hexGateway.substring(4, 6), 16),
|
|
1005
|
-
parseInt(hexGateway.substring(2, 4), 16),
|
|
1006
|
-
parseInt(hexGateway.substring(0, 2), 16)
|
|
1007
|
-
].join(".");
|
|
1008
|
-
rewriteLogger.info("Host gateway IP from /proc/net/route", { ip });
|
|
1009
|
-
cachedGatewayHost = ip;
|
|
1010
|
-
return cachedGatewayHost;
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
} catch {
|
|
1014
|
-
rewriteLogger.debug("Could not read /proc/net/route for default gateway lookup");
|
|
1015
|
-
}
|
|
1016
|
-
try {
|
|
1017
|
-
const hosts = readFileSync("/etc/hosts", "utf-8");
|
|
1018
|
-
for (const line of hosts.split("\n")) {
|
|
1019
|
-
const trimmed = line.trim();
|
|
1020
|
-
if (trimmed.startsWith("#") || trimmed === "") continue;
|
|
1021
|
-
const parts = trimmed.split(/\s+/);
|
|
1022
|
-
if (parts.length >= 2 && parts.slice(1).includes("host.docker.internal")) {
|
|
1023
|
-
const ip = parts[0];
|
|
1024
|
-
rewriteLogger.info("Host gateway IP from /etc/hosts (host.docker.internal)", { ip });
|
|
1025
|
-
cachedGatewayHost = ip;
|
|
1026
|
-
return cachedGatewayHost;
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
} catch {
|
|
1030
|
-
rewriteLogger.debug("Could not read /etc/hosts for host.docker.internal lookup");
|
|
1031
|
-
}
|
|
1032
958
|
rewriteLogger.warn("Could not resolve host gateway \u2014 localhost URLs will not be rewritten");
|
|
1033
959
|
cachedGatewayHost = null;
|
|
1034
960
|
return cachedGatewayHost;
|
|
@@ -1061,7 +987,7 @@ function rewriteLocalhostUrl(url) {
|
|
|
1061
987
|
}
|
|
1062
988
|
|
|
1063
989
|
// src/version.generated.ts
|
|
1064
|
-
var PLUGIN_UTILS_VERSION = "2.
|
|
990
|
+
var PLUGIN_UTILS_VERSION = "2.6.0";
|
|
1065
991
|
export {
|
|
1066
992
|
BUILTIN_TOOL_NAMES,
|
|
1067
993
|
DEFAULT_REQUEST_TIMEOUT_MS,
|