@owlmeans/llm 0.1.15 → 0.1.16
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/README.md +3 -4
- package/agent-meta/manifest.json +9 -9
- package/agent-meta/skills/llm/SKILL.md +54 -4
- package/agent-meta/skills/llm-prompt-caching/SKILL.md +135 -0
- package/build/consts.d.ts +36 -3
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +37 -4
- package/build/consts.js.map +1 -1
- package/build/execution/service.d.ts.map +1 -1
- package/build/execution/service.js +8 -3
- package/build/execution/service.js.map +1 -1
- package/build/execution/types.d.ts +20 -1
- package/build/execution/types.d.ts.map +1 -1
- package/build/execution/utils.d.ts +12 -1
- package/build/execution/utils.d.ts.map +1 -1
- package/build/execution/utils.js +22 -0
- package/build/execution/utils.js.map +1 -1
- package/build/helpers/cache.d.ts +17 -0
- package/build/helpers/cache.d.ts.map +1 -0
- package/build/helpers/cache.js +22 -0
- package/build/helpers/cache.js.map +1 -0
- package/build/helpers/index.d.ts +1 -0
- package/build/helpers/index.d.ts.map +1 -1
- package/build/helpers/index.js +1 -0
- package/build/helpers/index.js.map +1 -1
- package/build/helpers/spectate.d.ts.map +1 -1
- package/build/helpers/spectate.js +7 -0
- package/build/helpers/spectate.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/model.d.ts +1 -1
- package/build/model.d.ts.map +1 -1
- package/build/model.js +90 -16
- package/build/model.js.map +1 -1
- package/build/plugins/anthropic.d.ts.map +1 -1
- package/build/plugins/anthropic.js +136 -21
- package/build/plugins/anthropic.js.map +1 -1
- package/build/plugins/openai.d.ts +9 -0
- package/build/plugins/openai.d.ts.map +1 -1
- package/build/plugins/openai.js +23 -1
- package/build/plugins/openai.js.map +1 -1
- package/build/plugins/types.d.ts +38 -5
- package/build/plugins/types.d.ts.map +1 -1
- package/build/prompt/index.d.ts +5 -0
- package/build/prompt/index.d.ts.map +1 -0
- package/build/prompt/index.js +4 -0
- package/build/prompt/index.js.map +1 -0
- package/build/prompt/plugins.d.ts +24 -0
- package/build/prompt/plugins.d.ts.map +1 -0
- package/build/prompt/plugins.js +64 -0
- package/build/prompt/plugins.js.map +1 -0
- package/build/prompt/render.d.ts +28 -0
- package/build/prompt/render.d.ts.map +1 -0
- package/build/prompt/render.js +39 -0
- package/build/prompt/render.js.map +1 -0
- package/build/prompt/service.d.ts +16 -0
- package/build/prompt/service.d.ts.map +1 -0
- package/build/prompt/service.js +145 -0
- package/build/prompt/service.js.map +1 -0
- package/build/prompt/types.d.ts +101 -0
- package/build/prompt/types.d.ts.map +1 -0
- package/build/prompt/types.js +2 -0
- package/build/prompt/types.js.map +1 -0
- package/build/service.d.ts.map +1 -1
- package/build/service.js +3 -0
- package/build/service.js.map +1 -1
- package/build/types.d.ts +53 -3
- package/build/types.d.ts.map +1 -1
- package/build/utils/prompt.d.ts +14 -0
- package/build/utils/prompt.d.ts.map +1 -1
- package/build/utils/prompt.js +32 -0
- package/build/utils/prompt.js.map +1 -1
- package/package.json +13 -6
- package/src/consts.ts +43 -5
- package/src/execution/service.ts +9 -3
- package/src/execution/types.ts +21 -2
- package/src/execution/utils.ts +28 -1
- package/src/helpers/cache.ts +33 -0
- package/src/helpers/index.ts +1 -0
- package/src/helpers/spectate.ts +10 -0
- package/src/index.ts +1 -0
- package/src/model.ts +119 -16
- package/src/plugins/anthropic.ts +159 -20
- package/src/plugins/openai.ts +26 -1
- package/src/plugins/types.ts +42 -5
- package/src/prompt/index.ts +5 -0
- package/src/prompt/plugins.ts +69 -0
- package/src/prompt/render.ts +48 -0
- package/src/prompt/service.ts +194 -0
- package/src/prompt/types.ts +114 -0
- package/src/service.ts +3 -0
- package/src/types.ts +54 -3
- package/src/utils/prompt.ts +33 -0
- package/tests/execution.spec.ts +42 -0
- package/tests/plugins.spec.ts +279 -14
- package/tests/prompt.spec.ts +194 -0
- package/agent-meta/instructions/llm.instructions.md +0 -66
|
@@ -1,11 +1,59 @@
|
|
|
1
1
|
import { ChatAnthropic } from '@langchain/anthropic';
|
|
2
2
|
import { BadRequestError } from '@anthropic-ai/sdk';
|
|
3
|
-
import { ModelProvider, StructuredMode } from '@owlmeans/llm-common';
|
|
4
|
-
import { MAX_CACHE_BREAKPOINTS } from '../consts.js';
|
|
3
|
+
import { ModelProvider, PromptBlock, StructuredMode } from '@owlmeans/llm-common';
|
|
4
|
+
import { CHARS_PER_TOKEN, MAX_CACHE_BREAKPOINTS, MIN_CACHEABLE_TOKENS } from '../consts.js';
|
|
5
|
+
import { readConfig } from '../utils/config.js';
|
|
5
6
|
import { escalateMaxTokens, makeClientOptions } from './utils.js';
|
|
6
7
|
/** Model-name prefix that supports prompt caching through `cache_control` markers. */
|
|
7
8
|
const CACHEABLE_PREFIX = 'claude-';
|
|
8
9
|
export const ANTHROPIC_FAMILY = 'anthropic';
|
|
10
|
+
const supportsCache = (model) => model.modelName?.startsWith(CACHEABLE_PREFIX) === true;
|
|
11
|
+
/**
|
|
12
|
+
* Shortest prefix worth a breakpoint, in characters. Anthropic silently declines to
|
|
13
|
+
* create an entry below its own per-model minimum, so a marker there wastes one of the
|
|
14
|
+
* four breakpoints and reports a cache that was never written.
|
|
15
|
+
*/
|
|
16
|
+
const minCacheableChars = (model) => (readConfig(model).cacheMinTokens ?? MIN_CACHEABLE_TOKENS) * CHARS_PER_TOKEN;
|
|
17
|
+
/**
|
|
18
|
+
* The marker itself. `ttl` is omitted for the 5-minute default so the emitted bytes stay
|
|
19
|
+
* the classic shape — a request that differs only in an explicit `"ttl": "5m"` would not
|
|
20
|
+
* match a prefix cached without it.
|
|
21
|
+
*/
|
|
22
|
+
const marker = (ttl) => ttl === '1h' ? { type: 'ephemeral', ttl: '1h' } : { type: 'ephemeral' };
|
|
23
|
+
const contentLength = (content) => {
|
|
24
|
+
if (typeof content === 'string') {
|
|
25
|
+
return content.length;
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(content)) {
|
|
28
|
+
return content.reduce((sum, part) => {
|
|
29
|
+
const text = part.text;
|
|
30
|
+
return sum + (typeof text === 'string' ? text.length : 0);
|
|
31
|
+
}, 0);
|
|
32
|
+
}
|
|
33
|
+
return 0;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Put a breakpoint on a message's LAST content block, lifting string content into a block
|
|
37
|
+
* so the marker has somewhere to live. Idempotent, and it never mutates a block the
|
|
38
|
+
* caller owns — the array is rebuilt around a fresh copy of the final entry.
|
|
39
|
+
*/
|
|
40
|
+
const markMessage = (msg, mark) => {
|
|
41
|
+
if (typeof msg.content === 'string') {
|
|
42
|
+
msg.content = [{ type: 'text', text: msg.content, cache_control: mark }];
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (Array.isArray(msg.content) && msg.content.length > 0) {
|
|
46
|
+
const blocks = [...msg.content];
|
|
47
|
+
const last = blocks[blocks.length - 1];
|
|
48
|
+
if (last.cache_control != null) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
blocks[blocks.length - 1] = { ...last, cache_control: mark };
|
|
52
|
+
msg.content = blocks;
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
};
|
|
9
57
|
export const anthropicPlugin = {
|
|
10
58
|
type: ModelProvider.Anthropic,
|
|
11
59
|
family: ANTHROPIC_FAMILY,
|
|
@@ -57,30 +105,97 @@ export const anthropicPlugin = {
|
|
|
57
105
|
return new ChatAnthropic(cfg);
|
|
58
106
|
},
|
|
59
107
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
108
|
+
* Render the composed system prompt as Anthropic content blocks, one per section, with
|
|
109
|
+
* a breakpoint on each stability boundary:
|
|
110
|
+
*
|
|
111
|
+
* - after `Role` + `Skills` — the region every call of this role shares;
|
|
112
|
+
* - after `Packages` — varies with what the request mentions, so it gets its own
|
|
113
|
+
* entry and can never invalidate the block above it;
|
|
114
|
+
* - after the last block — so the whole system prompt is cached, which is the
|
|
115
|
+
* default this layer promises.
|
|
116
|
+
*
|
|
117
|
+
* Boundaries that coincide collapse into one. Marking stops as soon as the budget is
|
|
118
|
+
* spent, earliest boundary first — the earliest prefix is the one most calls share.
|
|
63
119
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
120
|
+
patchSystem: (blocks, { model, cacheMax, ttl }) => {
|
|
121
|
+
const content = blocks.map(block => ({ type: 'text', text: block.text }));
|
|
122
|
+
if (!supportsCache(model) || cacheMax < 1) {
|
|
123
|
+
return { content: content, breakpoints: 0 };
|
|
124
|
+
}
|
|
125
|
+
const lastOf = (...wanted) => blocks.reduce((found, block, i) => wanted.includes(block.block) ? i : found, -1);
|
|
126
|
+
// Closing the prompt is worth a breakpoint only when the last block is STABLE. A
|
|
127
|
+
// trailing `Context` changes every call, so marking it would pay a cache write every
|
|
128
|
+
// time and never read one back — it burns a breakpoint to buy nothing. A prompt that
|
|
129
|
+
// is ONLY context (a caller that has not adopted role/skills) is still worth marking,
|
|
130
|
+
// because there it IS the stable part.
|
|
131
|
+
const last = blocks.length - 1;
|
|
132
|
+
const closing = blocks[last].block === PromptBlock.Context && blocks.length > 1 ? -1 : last;
|
|
133
|
+
const boundaries = [...new Set([
|
|
134
|
+
lastOf(PromptBlock.Role, PromptBlock.Skills),
|
|
135
|
+
lastOf(PromptBlock.Packages),
|
|
136
|
+
closing,
|
|
137
|
+
].filter(index => index >= 0))].sort((a, b) => a - b);
|
|
138
|
+
const minChars = minCacheableChars(model);
|
|
139
|
+
let consumed = 0;
|
|
140
|
+
let chars = 0;
|
|
141
|
+
let next = 0;
|
|
142
|
+
for (let i = 0; i < content.length; i++) {
|
|
143
|
+
chars += blocks[i].text.length;
|
|
144
|
+
if (i !== boundaries[next]) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
next++;
|
|
148
|
+
if (chars < minChars || consumed >= cacheMax) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
content[i].cache_control = marker(ttl);
|
|
152
|
+
consumed++;
|
|
153
|
+
}
|
|
154
|
+
return { content: content, breakpoints: consumed };
|
|
155
|
+
},
|
|
156
|
+
/**
|
|
157
|
+
* One breakpoint, at the end of the stable message prefix (`cacheMax` messages).
|
|
158
|
+
*
|
|
159
|
+
* Not one marker per message: the request budget is {@link MAX_CACHE_BREAKPOINTS} in
|
|
160
|
+
* total across tools, system and messages, and the system prompt — the part that is
|
|
161
|
+
* genuinely identical between calls — has first claim on it. `reserved` is what the
|
|
162
|
+
* system prompt already spent.
|
|
163
|
+
*/
|
|
164
|
+
patchCache: (msgs, { model, useCache, cacheMax, reserved = 0, ttl = '5m' }) => {
|
|
165
|
+
if (!useCache || !supportsCache(model) || msgs.length === 0) {
|
|
66
166
|
return false;
|
|
67
|
-
const max = Math.min(cacheMax, MAX_CACHE_BREAKPOINTS);
|
|
68
|
-
let i = 0;
|
|
69
|
-
for (const msg of msgs) {
|
|
70
|
-
msg.content = typeof msg.content === 'string' ? [{
|
|
71
|
-
type: 'text',
|
|
72
|
-
text: msg.content,
|
|
73
|
-
cache_control: { type: 'ephemeral' },
|
|
74
|
-
}] : msg.content;
|
|
75
|
-
if (++i > max - 1)
|
|
76
|
-
break;
|
|
77
167
|
}
|
|
78
|
-
|
|
168
|
+
if (Math.min(cacheMax, MAX_CACHE_BREAKPOINTS - reserved) < 1) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
// The final message is the per-call payload, and `ensureJsonMention` / `applyNoThink`
|
|
172
|
+
// append to it — including it in the prefix would write a fresh entry every call and
|
|
173
|
+
// read none. The stable prefix therefore stops one short of the end.
|
|
174
|
+
const index = Math.min(cacheMax, msgs.length - 1) - 1;
|
|
175
|
+
const target = index >= 0 ? msgs[index] : null;
|
|
176
|
+
if (target == null) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
const chars = msgs.slice(0, index + 1)
|
|
180
|
+
.reduce((sum, msg) => sum + contentLength(msg.content), 0);
|
|
181
|
+
if (chars < minCacheableChars(model)) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return markMessage(target, marker(ttl));
|
|
79
185
|
},
|
|
80
186
|
/**
|
|
81
|
-
* A malformed request (bad schema, unsupported parameter, oversized `max_tokens
|
|
82
|
-
* cannot be fixed by retrying — surface it immediately instead
|
|
187
|
+
* A malformed request (bad schema, unsupported parameter, oversized `max_tokens`, too
|
|
188
|
+
* many cache breakpoints) cannot be fixed by retrying — surface it immediately instead
|
|
189
|
+
* of burning the budget.
|
|
190
|
+
*
|
|
191
|
+
* The `status` check is not redundant with the `instanceof`: `@langchain/anthropic`
|
|
192
|
+
* carries its OWN nested copy of `@anthropic-ai/sdk`, so the error it throws is an
|
|
193
|
+
* instance of a DIFFERENT `BadRequestError` class than the one imported here and the
|
|
194
|
+
* `instanceof` silently fails. That turned every fatal 400 into eight full retries —
|
|
195
|
+
* a single malformed request became minutes of thrash with the real cause buried.
|
|
83
196
|
*/
|
|
84
|
-
isFatal: e => e instanceof BadRequestError
|
|
197
|
+
isFatal: e => e instanceof BadRequestError || e?.status === 400
|
|
198
|
+
? e
|
|
199
|
+
: null,
|
|
85
200
|
};
|
|
86
201
|
//# sourceMappingURL=anthropic.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/plugins/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/plugins/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,15 @@ export declare const openAiFamily: {
|
|
|
17
17
|
* an aggregator route only to providers that actually support structured outputs.
|
|
18
18
|
*/
|
|
19
19
|
responseFormat: (toolName: string, schema: unknown) => Record<string, unknown>;
|
|
20
|
+
/**
|
|
21
|
+
* A 400 means the request itself is malformed — a schema the endpoint rejects, an
|
|
22
|
+
* unsupported parameter, a `max_tokens` above the model's per-request limit. Retrying
|
|
23
|
+
* re-sends the same shape (and the escalator raises `max_tokens`, making the last case
|
|
24
|
+
* strictly worse), so eight attempts only bury the real message. Matched on `status`
|
|
25
|
+
* rather than an SDK class: aggregators and nested SDK copies throw their own error
|
|
26
|
+
* types, and an `instanceof` against one of them silently never matches.
|
|
27
|
+
*/
|
|
28
|
+
isFatal: (e: unknown) => Error | null;
|
|
20
29
|
refine: ({ base, attempt, temperature, maxOutputCap }: LlmRefineParams) => BaseChatModel;
|
|
21
30
|
};
|
|
22
31
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/plugins/openai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAA;AAEhF,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAO5D,eAAO,MAAM,aAAa,WAAW,CAAA;AAErC,0FAA0F;AAC1F,eAAO,MAAM,YAAY;;kBAGT,aAAa,KAAG,OAAO;IAErC;;;OAGG;2BACoB,MAAM,KAAG,OAAO;IAEvC;;;;;OAKG;+BACwB,MAAM,UAAU,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/plugins/openai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAA;AAEhF,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAO5D,eAAO,MAAM,aAAa,WAAW,CAAA;AAErC,0FAA0F;AAC1F,eAAO,MAAM,YAAY;;kBAGT,aAAa,KAAG,OAAO;IAErC;;;OAGG;2BACoB,MAAM,KAAG,OAAO;IAEvC;;;;;OAKG;+BACwB,MAAM,UAAU,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAK5E;;;;;;;OAOG;iBACU,OAAO,KAAG,KAAK,GAAG,IAAI;2DAGoB,eAAe,KAAG,aAAa;CA2BvF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,SAoD1B,CAAA"}
|
package/build/plugins/openai.js
CHANGED
|
@@ -23,6 +23,15 @@ export const openAiFamily = {
|
|
|
23
23
|
type: 'json_schema',
|
|
24
24
|
json_schema: { name: toolName, schema, strict: false },
|
|
25
25
|
}),
|
|
26
|
+
/**
|
|
27
|
+
* A 400 means the request itself is malformed — a schema the endpoint rejects, an
|
|
28
|
+
* unsupported parameter, a `max_tokens` above the model's per-request limit. Retrying
|
|
29
|
+
* re-sends the same shape (and the escalator raises `max_tokens`, making the last case
|
|
30
|
+
* strictly worse), so eight attempts only bury the real message. Matched on `status`
|
|
31
|
+
* rather than an SDK class: aggregators and nested SDK copies throw their own error
|
|
32
|
+
* types, and an `instanceof` against one of them silently never matches.
|
|
33
|
+
*/
|
|
34
|
+
isFatal: (e) => e?.status === 400 ? e : null,
|
|
26
35
|
refine: ({ base, attempt, temperature, maxOutputCap }) => {
|
|
27
36
|
const model = base;
|
|
28
37
|
const currentTemperature = temperature ?? model.temperature ?? 0;
|
|
@@ -57,9 +66,20 @@ export const openAiPlugin = {
|
|
|
57
66
|
...openAiFamily,
|
|
58
67
|
type: ModelProvider.OpenAI,
|
|
59
68
|
structuredMode: (config) => config.structuredOutput === false ? StructuredMode.Tool : StructuredMode.Native,
|
|
60
|
-
build: ({ config, secret, callbacks }) => {
|
|
69
|
+
build: ({ alias, config, secret, callbacks }) => {
|
|
61
70
|
const model = config.model ??= 'gpt-5.4-mini';
|
|
62
71
|
const configuration = makeConfiguration({ baseURL: undefined, headers: config.headers });
|
|
72
|
+
// OpenAI's prompt cache is automatic and prefix-based — there is nothing to mark. The
|
|
73
|
+
// one lever a client has is routing: requests are dispatched by a hash of the prompt's
|
|
74
|
+
// opening tokens, and `prompt_cache_key` is mixed into that hash, so requests sharing
|
|
75
|
+
// a key land on the same backend and can actually hit each other's entries. The key
|
|
76
|
+
// must be stable and low-cardinality; the config alias IS the role, which is exactly
|
|
77
|
+
// the granularity at which a system prefix is shared.
|
|
78
|
+
//
|
|
79
|
+
// Deliberately NOT done for the `compatible` plugin: aggregators there run with
|
|
80
|
+
// `provider.require_parameters`, and an unknown top-level field can exclude every
|
|
81
|
+
// serving provider from the route.
|
|
82
|
+
const modelKwargs = { prompt_cache_key: config.cacheKey ?? alias };
|
|
63
83
|
// The Responses API models reject `temperature`/`topP`.
|
|
64
84
|
if (RESPONSES_API_PREFIXES.some(prefix => model.startsWith(prefix))) {
|
|
65
85
|
return new ChatOpenAI({
|
|
@@ -70,6 +90,7 @@ export const openAiPlugin = {
|
|
|
70
90
|
useResponsesApi: true,
|
|
71
91
|
metadata: { config },
|
|
72
92
|
callbacks,
|
|
93
|
+
modelKwargs,
|
|
73
94
|
...configuration,
|
|
74
95
|
});
|
|
75
96
|
}
|
|
@@ -82,6 +103,7 @@ export const openAiPlugin = {
|
|
|
82
103
|
maxRetries: 5,
|
|
83
104
|
metadata: { config },
|
|
84
105
|
callbacks,
|
|
106
|
+
modelKwargs,
|
|
85
107
|
...configuration,
|
|
86
108
|
});
|
|
87
109
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/plugins/openai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAGpE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEjE,yFAAyF;AACzF,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AAElD,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAA;AAErC,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,MAAM,EAAE,aAAa;IAErB,IAAI,EAAE,CAAC,KAAoB,EAAW,EAAE,CAAC,KAAK,YAAY,UAAU;IAEpE;;;OAGG;IACH,UAAU,EAAE,CAAC,QAAgB,EAAW,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;IAE/F;;;;;OAKG;IACH,cAAc,EAAE,CAAC,QAAgB,EAAE,MAAe,EAA2B,EAAE,CAAC,CAAC;QAC/E,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;KACvD,CAAC;IAEF,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAmB,EAAiB,EAAE;QACvF,MAAM,KAAK,GAAG,IAAkB,CAAA;QAChC,MAAM,kBAAkB,GAAG,WAAW,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,CAAA;QAChE,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;QAC3E,MAAM,UAAU,GAAG,KAAK,CAAC,SAExB,CAAA;QACD,kFAAkF;QAClF,qFAAqF;QACrF,uFAAuF;QACvF,uFAAuF;QACvF,8DAA8D;QAC9D,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,EAAE,SAAS,CAAA;QACnD,MAAM,WAAW,GAAG,OAAO,GAAG,CAAC,IAAI,OAAO,SAAS,EAAE,UAAU,KAAK,QAAQ;YAC1E,CAAC,CAAC;gBACA,GAAG,UAAU,CAAC,WAAW;gBACzB,SAAS,EAAE,EAAE,GAAG,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE;aAChH;YACD,CAAC,CAAC,UAAU,CAAC,WAAW,CAAA;QAE1B,OAAO,IAAI,UAAU,CAAC;YACpB,GAAG,UAAU;YACb,WAAW,EAAE,kBAAkB;YAC/B,SAAS;YACT,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChD,CAAC,CAAA;IACJ,CAAC;CACF,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,GAAG,YAAY;IAEf,IAAI,EAAE,aAAa,CAAC,MAAM;IAE1B,cAAc,EAAE,CAAC,MAAmB,EAAkB,EAAE,CACtD,MAAM,CAAC,gBAAgB,KAAK,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM;IAEjF,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/plugins/openai.ts"],"names":[],"mappings":"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"}
|
package/build/plugins/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
2
2
|
import type { BaseCallbackHandler, CallbackHandlerMethods } from '@langchain/core/callbacks/base';
|
|
3
|
-
import type { MessageFieldWithRole } from '@langchain/core/messages';
|
|
4
|
-
import type { StructuredMode } from '@owlmeans/llm-common';
|
|
3
|
+
import type { MessageContent, MessageFieldWithRole } from '@langchain/core/messages';
|
|
4
|
+
import type { CacheTtl, PromptBlock, StructuredMode } from '@owlmeans/llm-common';
|
|
5
5
|
import type { ModelConfig } from '../types.js';
|
|
6
6
|
export interface LlmBuildParams {
|
|
7
7
|
/** Alias the config was registered under — used only for error reporting. */
|
|
@@ -29,7 +29,29 @@ export interface LlmCacheParams {
|
|
|
29
29
|
/** The ORIGINAL (unrefined) model — refined instances do not always keep the name. */
|
|
30
30
|
model: BaseChatModel;
|
|
31
31
|
useCache: boolean;
|
|
32
|
+
/** How many leading messages form the stable prefix worth caching. */
|
|
32
33
|
cacheMax: number;
|
|
34
|
+
/** Breakpoints the composed system prompt already spent on this request. */
|
|
35
|
+
reserved?: number;
|
|
36
|
+
ttl?: CacheTtl;
|
|
37
|
+
}
|
|
38
|
+
/** One rendered section of the composed system prompt, in emission order. */
|
|
39
|
+
export interface LlmSystemBlock {
|
|
40
|
+
block: PromptBlock;
|
|
41
|
+
text: string;
|
|
42
|
+
}
|
|
43
|
+
export interface LlmSystemCacheParams {
|
|
44
|
+
/** The ORIGINAL (unrefined) model. */
|
|
45
|
+
model: BaseChatModel;
|
|
46
|
+
/** Breakpoint budget the system prompt may spend. */
|
|
47
|
+
cacheMax: number;
|
|
48
|
+
ttl: CacheTtl;
|
|
49
|
+
}
|
|
50
|
+
/** Provider-native rendering of the composed system prompt. */
|
|
51
|
+
export interface LlmSystemRender {
|
|
52
|
+
content: MessageContent;
|
|
53
|
+
/** Breakpoints consumed — subtracted from the message-level budget. */
|
|
54
|
+
breakpoints: number;
|
|
33
55
|
}
|
|
34
56
|
/**
|
|
35
57
|
* Everything that differs between inference providers, in one replaceable unit.
|
|
@@ -66,11 +88,22 @@ export interface LlmPlugin {
|
|
|
66
88
|
/** Provider-specific `response_format` for {@link StructuredMode.Native}. */
|
|
67
89
|
responseFormat?: (toolName: string, schema: unknown) => Record<string, unknown>;
|
|
68
90
|
/**
|
|
69
|
-
* Mark
|
|
70
|
-
*
|
|
71
|
-
*
|
|
91
|
+
* Mark the stable message prefix as cacheable, in-place. ONE breakpoint at the end of
|
|
92
|
+
* that prefix — not one per message: the budget is four per request and the system
|
|
93
|
+
* prompt has first claim on it. Returns `true` when a marker was actually placed.
|
|
94
|
+
* Omit for providers with no explicit prompt-cache markers.
|
|
72
95
|
*/
|
|
73
96
|
patchCache?: (msgs: MessageFieldWithRole[], params: LlmCacheParams) => boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Render the composed system blocks into provider-native content, placing cache
|
|
99
|
+
* breakpoints at the stability boundaries between blocks (see `PromptBlock`).
|
|
100
|
+
*
|
|
101
|
+
* Return `null` — or omit the method entirely — for providers whose prompt cache is
|
|
102
|
+
* automatic and prefix-based (OpenAI and friends): the service then joins the blocks
|
|
103
|
+
* into a plain string, which is all those providers need, since the block ORDER is
|
|
104
|
+
* what makes their prefix stable.
|
|
105
|
+
*/
|
|
106
|
+
patchSystem?: (blocks: LlmSystemBlock[], params: LlmSystemCacheParams) => LlmSystemRender | null;
|
|
74
107
|
/**
|
|
75
108
|
* Classify a thrown error as fatal for the retry loop. Return the error to throw
|
|
76
109
|
* immediately, or `null` to let it be retried.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAA;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AACjG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompt/index.ts"],"names":[],"mappings":"AACA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompt/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LlmPromptPlugin } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Block 0 — the base system prompt that tells the model who it is.
|
|
4
|
+
*
|
|
5
|
+
* The most stable thing in the whole request, so it goes first and every cache boundary
|
|
6
|
+
* sits behind it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const rolePlugin: LlmPromptPlugin;
|
|
9
|
+
/**
|
|
10
|
+
* Block 1 — the declared capabilities, rendered in a deterministic order.
|
|
11
|
+
*
|
|
12
|
+
* Registry skills and inline skills are merged by alias with inline winning, so a caller
|
|
13
|
+
* can override one registered entry without forking the catalogue.
|
|
14
|
+
*/
|
|
15
|
+
export declare const skillsPlugin: LlmPromptPlugin;
|
|
16
|
+
/**
|
|
17
|
+
* Block 3 — whatever the caller handed over verbatim, plus any skills requested for this
|
|
18
|
+
* one call. Emitted last and never marked cacheable: its content varies per request by
|
|
19
|
+
* definition, and a varying tail must not sit inside a prefix other calls depend on.
|
|
20
|
+
*/
|
|
21
|
+
export declare const contextPlugin: LlmPromptPlugin;
|
|
22
|
+
/** The plugins every {@link PromptService} starts with, in run order. */
|
|
23
|
+
export declare const BUILT_IN_PROMPT_PLUGINS: readonly LlmPromptPlugin[];
|
|
24
|
+
//# sourceMappingURL=plugins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../src/prompt/plugins.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,eAQxB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,eAa1B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,eAgB3B,CAAA;AAED,yEAAyE;AACzE,eAAO,MAAM,uBAAuB,EAAE,SAAS,eAAe,EAEpD,CAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PromptBlock } from '@owlmeans/llm-common';
|
|
2
|
+
import { joinChunks, renderSkill, sortSkills } from './render.js';
|
|
3
|
+
/**
|
|
4
|
+
* Block 0 — the base system prompt that tells the model who it is.
|
|
5
|
+
*
|
|
6
|
+
* The most stable thing in the whole request, so it goes first and every cache boundary
|
|
7
|
+
* sits behind it.
|
|
8
|
+
*/
|
|
9
|
+
export const rolePlugin = {
|
|
10
|
+
alias: 'role',
|
|
11
|
+
order: 0,
|
|
12
|
+
compose: ctx => {
|
|
13
|
+
if (ctx.input.role != null && ctx.input.role.trim() !== '') {
|
|
14
|
+
ctx.add(PromptBlock.Role, ctx.input.role);
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Block 1 — the declared capabilities, rendered in a deterministic order.
|
|
20
|
+
*
|
|
21
|
+
* Registry skills and inline skills are merged by alias with inline winning, so a caller
|
|
22
|
+
* can override one registered entry without forking the catalogue.
|
|
23
|
+
*/
|
|
24
|
+
export const skillsPlugin = {
|
|
25
|
+
alias: 'skills',
|
|
26
|
+
order: 10,
|
|
27
|
+
compose: ctx => {
|
|
28
|
+
const declared = ctx.resolve(ctx.input.skills ?? []);
|
|
29
|
+
const merged = new Map();
|
|
30
|
+
for (const skill of [...declared, ...(ctx.input.inline ?? [])]) {
|
|
31
|
+
merged.set(skill.alias, skill);
|
|
32
|
+
}
|
|
33
|
+
for (const skill of sortSkills([...merged.values()])) {
|
|
34
|
+
ctx.add(skill.block ?? PromptBlock.Skills, renderSkill(skill));
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Block 3 — whatever the caller handed over verbatim, plus any skills requested for this
|
|
40
|
+
* one call. Emitted last and never marked cacheable: its content varies per request by
|
|
41
|
+
* definition, and a varying tail must not sit inside a prefix other calls depend on.
|
|
42
|
+
*/
|
|
43
|
+
export const contextPlugin = {
|
|
44
|
+
alias: 'context',
|
|
45
|
+
order: 90,
|
|
46
|
+
compose: ctx => {
|
|
47
|
+
// Everything volatile is merged into ONE chunk rather than added piece by piece: the
|
|
48
|
+
// block carries no cache breakpoint, so there is nothing to gain from keeping the
|
|
49
|
+
// parts separable, and a single contiguous section reads as one instruction to the
|
|
50
|
+
// model instead of a pile of loose fragments.
|
|
51
|
+
const parts = [
|
|
52
|
+
...sortSkills(ctx.resolve(ctx.input.callSkills ?? [])).map(renderSkill),
|
|
53
|
+
...(ctx.input.context ?? []),
|
|
54
|
+
];
|
|
55
|
+
if (parts.length > 0) {
|
|
56
|
+
ctx.add(PromptBlock.Context, joinChunks(parts));
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
/** The plugins every {@link PromptService} starts with, in run order. */
|
|
61
|
+
export const BUILT_IN_PROMPT_PLUGINS = [
|
|
62
|
+
rolePlugin, skillsPlugin, contextPlugin,
|
|
63
|
+
];
|
|
64
|
+
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../src/prompt/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAElD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGjE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAoB;IACzC,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,GAAG,CAAC,EAAE;QACb,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC3C,CAAC;IACH,CAAC;CACF,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAoB;IAC3C,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,EAAE;IACT,OAAO,EAAE,GAAG,CAAC,EAAE;QACb,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;QACpD,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAA;QACjD,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAC/D,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QAChC,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;YACrD,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAA;QAChE,CAAC;IACH,CAAC;CACF,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAoB;IAC5C,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,EAAE;IACT,OAAO,EAAE,GAAG,CAAC,EAAE;QACb,qFAAqF;QACrF,kFAAkF;QAClF,mFAAmF;QACnF,8CAA8C;QAC9C,MAAM,KAAK,GAAG;YACZ,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC;YACvE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;SAC7B,CAAA;QACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;QACjD,CAAC;IACH,CAAC;CACF,CAAA;AAED,yEAAyE;AACzE,MAAM,CAAC,MAAM,uBAAuB,GAA+B;IACjE,UAAU,EAAE,YAAY,EAAE,aAAa;CAC/B,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SkillDefinition } from '@owlmeans/llm-common';
|
|
2
|
+
/**
|
|
3
|
+
* Separator between rendered chunks. Every join in this file goes through it: the
|
|
4
|
+
* composed prompt must be byte-identical between calls, so there is exactly one way to
|
|
5
|
+
* glue things together.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CHUNK_SEPARATOR = "\n\n";
|
|
8
|
+
/**
|
|
9
|
+
* Code-unit comparison, NOT `localeCompare`.
|
|
10
|
+
*
|
|
11
|
+
* `localeCompare` orders differently depending on the host's ICU data and locale, so two
|
|
12
|
+
* processes could render the same skill set in different orders and never share a cache
|
|
13
|
+
* entry. Skill aliases are ASCII slugs; a plain comparison is both correct and stable.
|
|
14
|
+
*/
|
|
15
|
+
export declare const compareAlias: (a: string, b: string) => number;
|
|
16
|
+
/** Deterministic skill order: declared weight first, alias as the tiebreaker. */
|
|
17
|
+
export declare const sortSkills: (skills: readonly SkillDefinition[]) => SkillDefinition[];
|
|
18
|
+
/** Fixed rendering of one skill. Changing this shape invalidates every cached prefix. */
|
|
19
|
+
export declare const renderSkill: (skill: SkillDefinition) => string;
|
|
20
|
+
/** Join rendered chunks into one block, dropping empties. */
|
|
21
|
+
export declare const joinChunks: (parts: readonly string[]) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Stable digest of a cache prefix — FNV-1a, so there is no crypto dependency and the
|
|
24
|
+
* result is identical on every runtime. Used as a provider cache-routing key (OpenAI's
|
|
25
|
+
* `prompt_cache_key`), never for security.
|
|
26
|
+
*/
|
|
27
|
+
export declare const prefixHash: (text: string) => string;
|
|
28
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/prompt/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3D;;;;GAIG;AACH,eAAO,MAAM,eAAe,SAAS,CAAA;AAErC;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAAoC,CAAA;AAExF,iFAAiF;AACjF,eAAO,MAAM,UAAU,GAAI,QAAQ,SAAS,eAAe,EAAE,KAAG,eAAe,EAK3E,CAAA;AAEJ,yFAAyF;AACzF,eAAO,MAAM,WAAW,GAAI,OAAO,eAAe,KAAG,MACO,CAAA;AAE5D,6DAA6D;AAC7D,eAAO,MAAM,UAAU,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,MAC4B,CAAA;AAElF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,MAOzC,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DEFAULT_SKILL_ORDER } from '@owlmeans/llm-common';
|
|
2
|
+
/**
|
|
3
|
+
* Separator between rendered chunks. Every join in this file goes through it: the
|
|
4
|
+
* composed prompt must be byte-identical between calls, so there is exactly one way to
|
|
5
|
+
* glue things together.
|
|
6
|
+
*/
|
|
7
|
+
export const CHUNK_SEPARATOR = '\n\n';
|
|
8
|
+
/**
|
|
9
|
+
* Code-unit comparison, NOT `localeCompare`.
|
|
10
|
+
*
|
|
11
|
+
* `localeCompare` orders differently depending on the host's ICU data and locale, so two
|
|
12
|
+
* processes could render the same skill set in different orders and never share a cache
|
|
13
|
+
* entry. Skill aliases are ASCII slugs; a plain comparison is both correct and stable.
|
|
14
|
+
*/
|
|
15
|
+
export const compareAlias = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
16
|
+
/** Deterministic skill order: declared weight first, alias as the tiebreaker. */
|
|
17
|
+
export const sortSkills = (skills) => [...skills].sort((a, b) => {
|
|
18
|
+
const left = a.order ?? DEFAULT_SKILL_ORDER;
|
|
19
|
+
const right = b.order ?? DEFAULT_SKILL_ORDER;
|
|
20
|
+
return left !== right ? left - right : compareAlias(a.alias, b.alias);
|
|
21
|
+
});
|
|
22
|
+
/** Fixed rendering of one skill. Changing this shape invalidates every cached prefix. */
|
|
23
|
+
export const renderSkill = (skill) => `## ${skill.title ?? skill.alias}\n\n${skill.body.trim()}`;
|
|
24
|
+
/** Join rendered chunks into one block, dropping empties. */
|
|
25
|
+
export const joinChunks = (parts) => parts.map(part => part.trim()).filter(part => part !== '').join(CHUNK_SEPARATOR);
|
|
26
|
+
/**
|
|
27
|
+
* Stable digest of a cache prefix — FNV-1a, so there is no crypto dependency and the
|
|
28
|
+
* result is identical on every runtime. Used as a provider cache-routing key (OpenAI's
|
|
29
|
+
* `prompt_cache_key`), never for security.
|
|
30
|
+
*/
|
|
31
|
+
export const prefixHash = (text) => {
|
|
32
|
+
let hash = 0x811c9dc5;
|
|
33
|
+
for (let i = 0; i < text.length; i++) {
|
|
34
|
+
hash ^= text.charCodeAt(i);
|
|
35
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
36
|
+
}
|
|
37
|
+
return hash.toString(36);
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/prompt/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAG1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAA;AAErC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAExF,iFAAiF;AACjF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAkC,EAAqB,EAAE,CAClF,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;IACxB,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,mBAAmB,CAAA;IAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,mBAAmB,CAAA;IAC5C,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;AACvE,CAAC,CAAC,CAAA;AAEJ,yFAAyF;AACzF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAsB,EAAU,EAAE,CAC5D,MAAM,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAA;AAE5D,6DAA6D;AAC7D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAwB,EAAU,EAAE,CAC7D,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;AAElF;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE;IACjD,IAAI,IAAI,GAAG,UAAU,CAAA;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QAC1B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AAC1B,CAAC,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BasicConfig, BasicContext } from '@owlmeans/context';
|
|
2
|
+
import type { PromptService, PromptServiceOptions, WithPromptService } from './types.js';
|
|
3
|
+
/** The part of {@link PromptService} this package implements — see {@link promptServiceApi}. */
|
|
4
|
+
export type PromptServiceApi = Pick<PromptService, 'use' | 'register' | 'has' | 'resolve' | 'skills' | 'compose'>;
|
|
5
|
+
/**
|
|
6
|
+
* Build the skill registry and composition chain WITHOUT registering a context service,
|
|
7
|
+
* so a consumer can spread it into its own `createService` and publish extra methods
|
|
8
|
+
* alongside it — the same pattern as `llmServiceApi` / `executionServiceApi`.
|
|
9
|
+
*
|
|
10
|
+
* `self` is late-bound because plugins resolve skills through the finished service, which
|
|
11
|
+
* a consumer may have extended.
|
|
12
|
+
*/
|
|
13
|
+
export declare const promptServiceApi: (options: PromptServiceOptions, self: () => PromptService) => PromptServiceApi;
|
|
14
|
+
export declare const makePromptService: (options?: PromptServiceOptions, alias?: string) => PromptService;
|
|
15
|
+
export declare const appendPromptService: <C extends BasicConfig, T extends BasicContext<C>>(ctx: T, options?: PromptServiceOptions, alias?: string) => T & WithPromptService;
|
|
16
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/prompt/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AASlE,OAAO,KAAK,EACoC,aAAa,EAAE,oBAAoB,EACjF,iBAAiB,EAClB,MAAM,YAAY,CAAA;AAKnB,gGAAgG;AAChG,MAAM,MAAM,gBAAgB,GAC1B,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAA;AAEpF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,SAAS,oBAAoB,EAC7B,MAAM,MAAM,aAAa,KACxB,gBAuIF,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,UAAS,oBAAyB,EAClC,QAAO,MAAuB,KAC7B,aAMF,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EAClF,KAAK,CAAC,EACN,UAAS,oBAAyB,EAClC,QAAO,MAAuB,KAC7B,CAAC,GAAG,iBAQN,CAAA"}
|