@quilltap/plugin-utils 2.3.0 → 2.4.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 +7 -0
- package/README.md +31 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +42 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -3
- package/dist/index.mjs.map +1 -1
- package/dist/providers/index.d.mts +64 -1
- package/dist/providers/index.d.ts +64 -1
- package/dist/providers/index.js +41 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/index.mjs +40 -2
- package/dist/providers/index.mjs.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to @quilltap/plugin-utils will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [2.4.0] - 2026-08-19
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `collapseLeadingSystemMessages(messages)` — folds a run of consecutive leading `system` messages into one, joining the contents with a blank line. Arrays with fewer than two leading system messages come back untouched (same reference).
|
|
10
|
+
- `OpenAICompatibleProvider` gained `acceptsRepeatedSystemMessages` (default `true`, so every existing subclass is byte-identical on the wire) and applies it through `applySystemMessagePolicy` in both the streaming and non-streaming body builds. A subclass pointing at a local runtime sets it `false`: the model's own chat template is what runs there, and the Qwen family — plus several Llama- and Gemma-derived templates — `raise_exception` on any system message after index 0, rejecting the whole request. Quilltap emits up to three leading system blocks so its cache breakpoints survive, so every non-opening turn against such a model failed outright. (Quilltap bug 82.)
|
|
11
|
+
|
|
5
12
|
## [2.3.0] - 2026-08-15
|
|
6
13
|
|
|
7
14
|
### Added
|
package/README.md
CHANGED
|
@@ -150,6 +150,37 @@ This gives you a complete `LLMProvider` implementation with:
|
|
|
150
150
|
npm install openai
|
|
151
151
|
```
|
|
152
152
|
|
|
153
|
+
### Profile Parameters
|
|
154
|
+
|
|
155
|
+
A connection profile's `parameters` blob is free-form JSON, handed to the
|
|
156
|
+
provider as `LLMParams.profileParameters`. A provider that never reads it drops
|
|
157
|
+
every setting the user saved, in silence — so forwarding is opt-in but explicit,
|
|
158
|
+
and always allow-listed:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import { applyProfileParameters } from '@quilltap/plugin-utils';
|
|
162
|
+
|
|
163
|
+
const MY_ALLOWLIST = ['top_k', 'min_p', 'reasoning_effort'] as const;
|
|
164
|
+
|
|
165
|
+
applyProfileParameters(body, params, MY_ALLOWLIST, (key, value, callParams, target) => {
|
|
166
|
+
// Return the value to send, or `undefined` to omit the key.
|
|
167
|
+
// Write into `target` to send it under a different key entirely.
|
|
168
|
+
return value;
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`undefined`, `null` and the empty string omit the key — the empty string is what
|
|
173
|
+
the schema-driven profile editor stores for "use the model default". Never
|
|
174
|
+
spread the blob: `model`, `messages`, `stream`, `stream_options` and `tools`
|
|
175
|
+
must stay unreachable from a profile.
|
|
176
|
+
|
|
177
|
+
Subclasses of `OpenAICompatibleProvider` get this by declaring
|
|
178
|
+
`profileParamAllowlist` (empty by default, so a subclass that declares nothing
|
|
179
|
+
is byte-identical on the wire) and optionally overriding `normalizeProfileParam`;
|
|
180
|
+
providers that implement `TextProvider` directly call the function themselves.
|
|
181
|
+
The keys must match whatever the plugin's `getProviderOptionsSchema()` renders,
|
|
182
|
+
or a field the editor draws goes nowhere.
|
|
183
|
+
|
|
153
184
|
### System Prompt Plugin Utilities
|
|
154
185
|
|
|
155
186
|
Create system prompt plugins that provide character prompt templates from `.md` files:
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { AnthropicToolDefinition, CharacterPluginDataEntry, CharacterPluginDataMap, GoogleToolDefinition, LogContext, LogLevel, OpenAIToolDefinition, PluginLogger, ToolCall, ToolCallRequest, ToolFormatOptions, ToolResult, UniversalTool, createConsoleLogger, createNoopLogger } from '@quilltap/plugin-types';
|
|
2
2
|
export { T as ToolCallFormat, a as ToolConvertTarget, b as applyDescriptionLimit, c as convertFromAnthropicFormat, d as convertFromGoogleFormat, e as convertOpenAIToAnthropicFormat, f as convertOpenAIToGoogleFormat, g as convertToAnthropicFormat, h as convertToGoogleFormat, i as convertToolTo, j as convertToolsTo, k as detectToolCallFormat, l as hasToolCalls, p as parseAnthropicToolCalls, m as parseGoogleToolCalls, n as parseOpenAIToolCalls, o as parseToolCalls } from './converters-BPYo8xdH.mjs';
|
|
3
3
|
export { PluginLoggerWithChild, __clearCoreLoggerFactory, __injectCoreLoggerFactory, createPluginLogger, getLogLevelFromEnv, hasCoreLogger } from './logging/index.mjs';
|
|
4
|
-
export { DEFAULT_REQUEST_TIMEOUT_MS, OpenAICompatibleProvider, OpenAICompatibleProviderConfig, ProfileParamNormalizer, applyProfileParameters, buildRequestAbortSignal, buildSdkClientOptions, buildSdkRequestOptions, resolveRequestTimeoutMs } from './providers/index.mjs';
|
|
4
|
+
export { DEFAULT_REQUEST_TIMEOUT_MS, OpenAICompatibleProvider, OpenAICompatibleProviderConfig, ProfileParamNormalizer, applyProfileParameters, buildRequestAbortSignal, buildSdkClientOptions, buildSdkRequestOptions, collapseLeadingSystemMessages, resolveRequestTimeoutMs } from './providers/index.mjs';
|
|
5
5
|
export { CreateSystemPromptPluginOptions, createSystemPromptPlugin, validateSystemPromptPlugin } from './system-prompts/index.mjs';
|
|
6
6
|
export { isVMEnvironment, resolveHostGateway, rewriteLocalhostUrl } from './host-rewrite.mjs';
|
|
7
7
|
import 'openai';
|
|
@@ -124,6 +124,6 @@ declare function getQuilltapUserAgent(): string;
|
|
|
124
124
|
* Version of the plugin-utils package.
|
|
125
125
|
* Can be used at runtime to check compatibility.
|
|
126
126
|
*/
|
|
127
|
-
declare const PLUGIN_UTILS_VERSION = "2.
|
|
127
|
+
declare const PLUGIN_UTILS_VERSION = "2.4.0";
|
|
128
128
|
|
|
129
129
|
export { BUILTIN_TOOL_NAMES, PLUGIN_UTILS_VERSION, __clearQuilltapVersion, __injectQuilltapVersion, getBuiltinToolNames, getQuilltapUserAgent, getQuilltapVersion };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { AnthropicToolDefinition, CharacterPluginDataEntry, CharacterPluginDataMap, GoogleToolDefinition, LogContext, LogLevel, OpenAIToolDefinition, PluginLogger, ToolCall, ToolCallRequest, ToolFormatOptions, ToolResult, UniversalTool, createConsoleLogger, createNoopLogger } from '@quilltap/plugin-types';
|
|
2
2
|
export { T as ToolCallFormat, a as ToolConvertTarget, b as applyDescriptionLimit, c as convertFromAnthropicFormat, d as convertFromGoogleFormat, e as convertOpenAIToAnthropicFormat, f as convertOpenAIToGoogleFormat, g as convertToAnthropicFormat, h as convertToGoogleFormat, i as convertToolTo, j as convertToolsTo, k as detectToolCallFormat, l as hasToolCalls, p as parseAnthropicToolCalls, m as parseGoogleToolCalls, n as parseOpenAIToolCalls, o as parseToolCalls } from './converters-BPYo8xdH.js';
|
|
3
3
|
export { PluginLoggerWithChild, __clearCoreLoggerFactory, __injectCoreLoggerFactory, createPluginLogger, getLogLevelFromEnv, hasCoreLogger } from './logging/index.js';
|
|
4
|
-
export { DEFAULT_REQUEST_TIMEOUT_MS, OpenAICompatibleProvider, OpenAICompatibleProviderConfig, ProfileParamNormalizer, applyProfileParameters, buildRequestAbortSignal, buildSdkClientOptions, buildSdkRequestOptions, resolveRequestTimeoutMs } from './providers/index.js';
|
|
4
|
+
export { DEFAULT_REQUEST_TIMEOUT_MS, OpenAICompatibleProvider, OpenAICompatibleProviderConfig, ProfileParamNormalizer, applyProfileParameters, buildRequestAbortSignal, buildSdkClientOptions, buildSdkRequestOptions, collapseLeadingSystemMessages, resolveRequestTimeoutMs } from './providers/index.js';
|
|
5
5
|
export { CreateSystemPromptPluginOptions, createSystemPromptPlugin, validateSystemPromptPlugin } from './system-prompts/index.js';
|
|
6
6
|
export { isVMEnvironment, resolveHostGateway, rewriteLocalhostUrl } from './host-rewrite.js';
|
|
7
7
|
import 'openai';
|
|
@@ -124,6 +124,6 @@ declare function getQuilltapUserAgent(): string;
|
|
|
124
124
|
* Version of the plugin-utils package.
|
|
125
125
|
* Can be used at runtime to check compatibility.
|
|
126
126
|
*/
|
|
127
|
-
declare const PLUGIN_UTILS_VERSION = "2.
|
|
127
|
+
declare const PLUGIN_UTILS_VERSION = "2.4.0";
|
|
128
128
|
|
|
129
129
|
export { BUILTIN_TOOL_NAMES, PLUGIN_UTILS_VERSION, __clearQuilltapVersion, __injectQuilltapVersion, getBuiltinToolNames, getQuilltapUserAgent, getQuilltapVersion };
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ __export(src_exports, {
|
|
|
43
43
|
buildRequestAbortSignal: () => buildRequestAbortSignal,
|
|
44
44
|
buildSdkClientOptions: () => buildSdkClientOptions,
|
|
45
45
|
buildSdkRequestOptions: () => buildSdkRequestOptions,
|
|
46
|
+
collapseLeadingSystemMessages: () => collapseLeadingSystemMessages,
|
|
46
47
|
convertFromAnthropicFormat: () => convertFromAnthropicFormat,
|
|
47
48
|
convertFromGoogleFormat: () => convertFromGoogleFormat,
|
|
48
49
|
convertOpenAIToAnthropicFormat: () => convertOpenAIToAnthropicFormat,
|
|
@@ -443,6 +444,21 @@ function applyProfileParameters(body, params, allowlist, normalize) {
|
|
|
443
444
|
}
|
|
444
445
|
}
|
|
445
446
|
|
|
447
|
+
// src/providers/system-messages.ts
|
|
448
|
+
function collapseLeadingSystemMessages(messages) {
|
|
449
|
+
let runLength = 0;
|
|
450
|
+
while (runLength < messages.length && messages[runLength].role === "system") {
|
|
451
|
+
runLength++;
|
|
452
|
+
}
|
|
453
|
+
if (runLength < 2) return messages;
|
|
454
|
+
const run = messages.slice(0, runLength);
|
|
455
|
+
const merged = {
|
|
456
|
+
...run[0],
|
|
457
|
+
content: run.map((m) => m.content ?? "").filter((c) => c.length > 0).join("\n\n")
|
|
458
|
+
};
|
|
459
|
+
return [merged, ...messages.slice(runLength)];
|
|
460
|
+
}
|
|
461
|
+
|
|
446
462
|
// src/providers/openai-compatible.ts
|
|
447
463
|
var DEFAULT_MAX_RETRIES = 2;
|
|
448
464
|
var OpenAICompatibleProvider = class {
|
|
@@ -458,6 +474,18 @@ var OpenAICompatibleProvider = class {
|
|
|
458
474
|
this.supportedMimeTypes = [];
|
|
459
475
|
/** Web search is not supported */
|
|
460
476
|
this.supportsWebSearch = false;
|
|
477
|
+
/**
|
|
478
|
+
* Whether the endpoint tolerates more than one leading `system` message.
|
|
479
|
+
*
|
|
480
|
+
* True for every hosted service — and so the default, which keeps the
|
|
481
|
+
* outbound bytes of OpenRouter, Z.AI and every other subclass exactly as they
|
|
482
|
+
* were. A subclass that points at a local runtime applying the *model's* chat
|
|
483
|
+
* template sets this false: several template families reject a system message
|
|
484
|
+
* anywhere but index 0, and Quilltap's context builder deliberately emits up
|
|
485
|
+
* to three of them so its cache breakpoints survive. See Bug 82 and
|
|
486
|
+
* {@link collapseLeadingSystemMessages}.
|
|
487
|
+
*/
|
|
488
|
+
this.acceptsRepeatedSystemMessages = true;
|
|
461
489
|
/**
|
|
462
490
|
* Profile-parameter keys this provider forwards from
|
|
463
491
|
* `LLMParams.profileParameters` onto the request body.
|
|
@@ -485,6 +513,14 @@ var OpenAICompatibleProvider = class {
|
|
|
485
513
|
}
|
|
486
514
|
this.logger = createPluginLogger(`${this.providerName}Provider`);
|
|
487
515
|
}
|
|
516
|
+
/**
|
|
517
|
+
* Apply {@link acceptsRepeatedSystemMessages} to a mapped wire-message array.
|
|
518
|
+
* Called by both body builds so the streaming and non-streaming shapes cannot
|
|
519
|
+
* drift apart.
|
|
520
|
+
*/
|
|
521
|
+
applySystemMessagePolicy(messages) {
|
|
522
|
+
return this.acceptsRepeatedSystemMessages ? messages : collapseLeadingSystemMessages(messages);
|
|
523
|
+
}
|
|
488
524
|
/**
|
|
489
525
|
* Collects attachment failures for messages with attachments.
|
|
490
526
|
* Since attachments are not supported, all attachments are marked as failed.
|
|
@@ -613,7 +649,7 @@ var OpenAICompatibleProvider = class {
|
|
|
613
649
|
this.validateApiKeyRequirement(apiKey);
|
|
614
650
|
const attachmentResults = this.collectAttachmentFailures(params);
|
|
615
651
|
const client = this.createClient(apiKey);
|
|
616
|
-
const
|
|
652
|
+
const mappedMessages = params.messages.filter((m) => {
|
|
617
653
|
if (m.role === "tool" && !m.toolCallId) return false;
|
|
618
654
|
return true;
|
|
619
655
|
}).map((m) => {
|
|
@@ -640,6 +676,7 @@ var OpenAICompatibleProvider = class {
|
|
|
640
676
|
content: m.content
|
|
641
677
|
};
|
|
642
678
|
});
|
|
679
|
+
const messages = this.applySystemMessagePolicy(mappedMessages);
|
|
643
680
|
const body = {
|
|
644
681
|
model: params.model,
|
|
645
682
|
messages,
|
|
@@ -692,7 +729,7 @@ var OpenAICompatibleProvider = class {
|
|
|
692
729
|
this.validateApiKeyRequirement(apiKey);
|
|
693
730
|
const attachmentResults = this.collectAttachmentFailures(params);
|
|
694
731
|
const client = this.createClient(apiKey);
|
|
695
|
-
const
|
|
732
|
+
const mappedMessages = params.messages.filter((m) => {
|
|
696
733
|
if (m.role === "tool" && !m.toolCallId) return false;
|
|
697
734
|
return true;
|
|
698
735
|
}).map((m) => {
|
|
@@ -719,6 +756,7 @@ var OpenAICompatibleProvider = class {
|
|
|
719
756
|
content: m.content
|
|
720
757
|
};
|
|
721
758
|
});
|
|
759
|
+
const messages = this.applySystemMessagePolicy(mappedMessages);
|
|
722
760
|
const body = {
|
|
723
761
|
model: params.model,
|
|
724
762
|
messages,
|
|
@@ -1100,7 +1138,7 @@ function rewriteLocalhostUrl(url) {
|
|
|
1100
1138
|
}
|
|
1101
1139
|
|
|
1102
1140
|
// src/version.generated.ts
|
|
1103
|
-
var PLUGIN_UTILS_VERSION = "2.
|
|
1141
|
+
var PLUGIN_UTILS_VERSION = "2.4.0";
|
|
1104
1142
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1105
1143
|
0 && (module.exports = {
|
|
1106
1144
|
BUILTIN_TOOL_NAMES,
|
|
@@ -1116,6 +1154,7 @@ var PLUGIN_UTILS_VERSION = "2.3.0";
|
|
|
1116
1154
|
buildRequestAbortSignal,
|
|
1117
1155
|
buildSdkClientOptions,
|
|
1118
1156
|
buildSdkRequestOptions,
|
|
1157
|
+
collapseLeadingSystemMessages,
|
|
1119
1158
|
convertFromAnthropicFormat,
|
|
1120
1159
|
convertFromGoogleFormat,
|
|
1121
1160
|
convertOpenAIToAnthropicFormat,
|