promptopskit 0.4.2 → 0.5.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/README.md +98 -57
- package/SKILL.md +360 -6
- package/dist/chunk-6BOUQVSX.js +130 -0
- package/dist/chunk-6BOUQVSX.js.map +1 -0
- package/dist/{chunk-7MRMN3SW.js → chunk-6VLKZCNS.js} +6 -4
- package/dist/chunk-6VLKZCNS.js.map +1 -0
- package/dist/{chunk-HWEVRBKZ.js → chunk-AGTGIZMR.js} +6 -2
- package/dist/chunk-AGTGIZMR.js.map +1 -0
- package/dist/{chunk-XL76NHZR.js → chunk-D75HKF64.js} +6 -4
- package/dist/chunk-D75HKF64.js.map +1 -0
- package/dist/{chunk-5AAYDOPU.js → chunk-IN4KT5EU.js} +4 -3
- package/dist/chunk-IN4KT5EU.js.map +1 -0
- package/dist/{chunk-JKBWC5WJ.js → chunk-K6ZU3CGV.js} +22 -5
- package/dist/chunk-K6ZU3CGV.js.map +1 -0
- package/dist/{chunk-YI4LILPY.js → chunk-KN7H4JRK.js} +61 -4
- package/dist/chunk-KN7H4JRK.js.map +1 -0
- package/dist/{chunk-Z4IPWEUU.js → chunk-LNGHGGJN.js} +6 -4
- package/dist/chunk-LNGHGGJN.js.map +1 -0
- package/dist/{chunk-MI3M6KDD.js → chunk-QK3WKE3K.js} +6 -4
- package/dist/chunk-QK3WKE3K.js.map +1 -0
- package/dist/cli/index.js +27 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +233 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +32 -10
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +82 -8
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.d.cts +2 -2
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +3 -3
- package/dist/providers/gemini.cjs +82 -8
- package/dist/providers/gemini.cjs.map +1 -1
- package/dist/providers/gemini.d.cts +2 -2
- package/dist/providers/gemini.d.ts +2 -2
- package/dist/providers/gemini.js +3 -3
- package/dist/providers/llmasaservice.cjs +1467 -0
- package/dist/providers/llmasaservice.cjs.map +1 -0
- package/dist/providers/llmasaservice.d.cts +28 -0
- package/dist/providers/llmasaservice.d.ts +28 -0
- package/dist/providers/llmasaservice.js +20 -0
- package/dist/providers/llmasaservice.js.map +1 -0
- package/dist/providers/openai-responses.cjs +82 -8
- package/dist/providers/openai-responses.cjs.map +1 -1
- package/dist/providers/openai-responses.d.cts +2 -2
- package/dist/providers/openai-responses.d.ts +2 -2
- package/dist/providers/openai-responses.js +3 -3
- package/dist/providers/openai.cjs +82 -8
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.d.cts +2 -2
- package/dist/providers/openai.d.ts +2 -2
- package/dist/providers/openai.js +3 -3
- package/dist/providers/openrouter.cjs +83 -8
- package/dist/providers/openrouter.cjs.map +1 -1
- package/dist/providers/openrouter.d.cts +2 -2
- package/dist/providers/openrouter.d.ts +2 -2
- package/dist/providers/openrouter.js +4 -4
- package/dist/{schema-B9A1zLRk.d.cts → schema-D-RI4w-k.d.cts} +695 -183
- package/dist/{schema-B9A1zLRk.d.ts → schema-D-RI4w-k.d.ts} +695 -183
- package/dist/testing.cjs +21 -4
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/{types-DjGAwJxC.d.ts → types-B3dxBGu6.d.ts} +18 -6
- package/dist/{types-DpbzzZO2.d.cts → types-DbTAjlTN.d.cts} +18 -6
- package/dist/usagetap/index.cjs +6 -1
- package/dist/usagetap/index.cjs.map +1 -1
- package/dist/usagetap/index.d.cts +4 -3
- package/dist/usagetap/index.d.ts +4 -3
- package/dist/usagetap/index.js +3 -1
- package/package.json +11 -1
- package/dist/chunk-5AAYDOPU.js.map +0 -1
- package/dist/chunk-7MRMN3SW.js.map +0 -1
- package/dist/chunk-HWEVRBKZ.js.map +0 -1
- package/dist/chunk-JKBWC5WJ.js.map +0 -1
- package/dist/chunk-MI3M6KDD.js.map +0 -1
- package/dist/chunk-XL76NHZR.js.map +0 -1
- package/dist/chunk-YI4LILPY.js.map +0 -1
- package/dist/chunk-Z4IPWEUU.js.map +0 -1
package/SKILL.md
CHANGED
|
@@ -8,7 +8,325 @@ description: Guidance for creating and editing promptopskit prompt files, defaul
|
|
|
8
8
|
This project uses **promptopskit** to manage LLM prompts as code.
|
|
9
9
|
Prompts live in markdown files with YAML front matter, are validated against
|
|
10
10
|
a schema, and render into provider-specific request bodies (OpenAI, Anthropic,
|
|
11
|
-
Gemini, OpenRouter, and OpenAI Responses). Follow these instructions when creating or editing prompts.
|
|
11
|
+
Gemini, OpenRouter, LLMAsAService, and OpenAI Responses). Follow these instructions when creating or editing prompts.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## User request intents
|
|
16
|
+
|
|
17
|
+
When a user asks for prompt work, infer their intent from phrasing and act directly.
|
|
18
|
+
Do not stop at explanation when the user is asking for a file or code artifact.
|
|
19
|
+
|
|
20
|
+
### Create a new prompt
|
|
21
|
+
|
|
22
|
+
Treat requests like these as instructions to create a new prompt markdown file:
|
|
23
|
+
|
|
24
|
+
- "Create a prompt that ..."
|
|
25
|
+
- "Add a prompt that ..."
|
|
26
|
+
- "Write a prompt for ..."
|
|
27
|
+
- "Make a prompt to ..."
|
|
28
|
+
- "Build me a prompt that ..."
|
|
29
|
+
- "I need a prompt that ..."
|
|
30
|
+
- "Scaffold a prompt for ..."
|
|
31
|
+
- "Create an eval/rewrite/classifier/extractor/summarizer prompt ..."
|
|
32
|
+
|
|
33
|
+
Behavior:
|
|
34
|
+
|
|
35
|
+
1. Create a new `kebab-case.md` file under the project's prompt source directory
|
|
36
|
+
(`./prompts` by default, or the existing prompt folder used by the repo).
|
|
37
|
+
2. Give the file a meaningful name derived from the task, not a generic name like
|
|
38
|
+
`prompt.md` or `new-prompt.md`.
|
|
39
|
+
3. Set `id` to a stable slash path or camel/snake identifier that matches local
|
|
40
|
+
conventions. Prefer path-like ids such as `support/reply`,
|
|
41
|
+
`content/seo-brief`, or `examples/basic` when prompts are organized in folders.
|
|
42
|
+
4. Include all appropriate defaults for the requested use case:
|
|
43
|
+
- Always include `id` and `schema_version: 1`.
|
|
44
|
+
- Include `description` when the purpose is not obvious from the id.
|
|
45
|
+
- Include `provider` and `model` only if they are requested or not supplied by
|
|
46
|
+
a nearby `defaults.md`.
|
|
47
|
+
- Include `sampling`, `reasoning`, `response`, `tools`, `cache`,
|
|
48
|
+
`provider_options`, or `raw` only when the prompt behavior requires them.
|
|
49
|
+
- Include `context.inputs` for every `{{ variable }}` in the body.
|
|
50
|
+
- Use object-form inputs with `non_empty: true`, `max_size`, `trim`, and
|
|
51
|
+
validation controls when the input is user-provided or unbounded.
|
|
52
|
+
- Add `context.history.max_items` for chat or support prompts that should
|
|
53
|
+
preserve bounded conversation history through compaction.
|
|
54
|
+
- Add `# Notes` only for authoring details, examples, or explanations that
|
|
55
|
+
must not be sent to the model.
|
|
56
|
+
5. If the prompt should return JSON or another structured result, define
|
|
57
|
+
`response.format: json` and a JSON Schema in `response.schema`.
|
|
58
|
+
6. When the user gives a vague task, choose sensible placeholders and defaults
|
|
59
|
+
from the task instead of asking for every detail. Ask only if the missing
|
|
60
|
+
detail would change the prompt's purpose, provider, or output contract.
|
|
61
|
+
7. After writing the file, run or recommend `promptopskit validate` for the prompt
|
|
62
|
+
source directory.
|
|
63
|
+
|
|
64
|
+
Example response to "Create a prompt that turns a support ticket into a concise triage summary":
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
---
|
|
68
|
+
id: support/triage-summary
|
|
69
|
+
schema_version: 1
|
|
70
|
+
description: Summarize a support ticket for triage.
|
|
71
|
+
context:
|
|
72
|
+
inputs:
|
|
73
|
+
- name: ticket
|
|
74
|
+
non_empty: true
|
|
75
|
+
trim: true
|
|
76
|
+
max_size: 12000
|
|
77
|
+
reject_secrets: true
|
|
78
|
+
response:
|
|
79
|
+
format: json
|
|
80
|
+
schema_name: support_triage_summary
|
|
81
|
+
schema:
|
|
82
|
+
type: object
|
|
83
|
+
additionalProperties: false
|
|
84
|
+
required: [summary, urgency, category, next_action]
|
|
85
|
+
properties:
|
|
86
|
+
summary:
|
|
87
|
+
type: string
|
|
88
|
+
urgency:
|
|
89
|
+
type: string
|
|
90
|
+
enum: [low, medium, high]
|
|
91
|
+
category:
|
|
92
|
+
type: string
|
|
93
|
+
next_action:
|
|
94
|
+
type: string
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
# System instructions
|
|
98
|
+
|
|
99
|
+
You summarize support tickets for a triage queue. Be concise, specific, and avoid
|
|
100
|
+
inventing details that are not in the ticket.
|
|
101
|
+
|
|
102
|
+
# Prompt template
|
|
103
|
+
|
|
104
|
+
Summarize this support ticket:
|
|
105
|
+
|
|
106
|
+
{{ ticket }}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Generate provider render code
|
|
110
|
+
|
|
111
|
+
Treat requests like these as instructions to generate code that renders a prompt
|
|
112
|
+
into a provider request body:
|
|
113
|
+
|
|
114
|
+
- "render the body for the prompt [name] for openai"
|
|
115
|
+
- "generate the body for [name] using anthropic"
|
|
116
|
+
- "create the call for prompt [name] for google"
|
|
117
|
+
- "convert prompt [name] to an openrouter request"
|
|
118
|
+
- "show me the OpenAI body for [name]"
|
|
119
|
+
- "generate the Anthropic call for the prompt [name]"
|
|
120
|
+
- "render/generate/build/create/produce the request/body/call/payload/messages
|
|
121
|
+
for prompt [name] with provider [provider]"
|
|
122
|
+
- "turn [name] into a provider request for openai/anthropic/google/gemini/openrouter/llmasaservice"
|
|
123
|
+
- "wire up prompt [name] to OpenAI/Anthropic/Gemini/OpenRouter/LLMAsAService"
|
|
124
|
+
- "give me code to call [provider] with prompt [name]"
|
|
125
|
+
|
|
126
|
+
Provider aliases:
|
|
127
|
+
|
|
128
|
+
| User says | Use provider |
|
|
129
|
+
|-----------|--------------|
|
|
130
|
+
| `openai`, `chat completions`, `OpenAI chat` | `openai` |
|
|
131
|
+
| `responses`, `OpenAI Responses`, `responses api` | `openai-responses` |
|
|
132
|
+
| `anthropic`, `claude` | `anthropic` |
|
|
133
|
+
| `google`, `gemini` | `gemini` |
|
|
134
|
+
| `openrouter` | `openrouter` |
|
|
135
|
+
| `llmasaservice`, `llmasaservice.io`, `llm gateway` | `llmasaservice` |
|
|
136
|
+
|
|
137
|
+
Behavior:
|
|
138
|
+
|
|
139
|
+
1. Generate code unless the user explicitly asks for only the raw rendered JSON.
|
|
140
|
+
2. Prefer `createPromptOpsKit().renderPrompt()` for server-side app code that loads
|
|
141
|
+
prompt source or compiled JSON by path.
|
|
142
|
+
3. Prefer provider adapters (`openaiAdapter`, `anthropicAdapter`,
|
|
143
|
+
`geminiAdapter`, `openrouterAdapter`, `llmasaserviceAdapter`) when the user asks for provider-specific
|
|
144
|
+
integration code or already has a compiled asset.
|
|
145
|
+
4. Include `variables` for every declared prompt input, using realistic placeholder
|
|
146
|
+
values or function parameters.
|
|
147
|
+
5. Include `history` only if the prompt is chat-style or declares
|
|
148
|
+
`context.history`.
|
|
149
|
+
6. Check `returnMessage` before reading `request` when using `kit.renderPrompt()`
|
|
150
|
+
or `adapter.renderPrompt()`.
|
|
151
|
+
7. Return or pass `request.body` as the provider request payload; `request.provider`
|
|
152
|
+
and `request.model` are metadata for the caller.
|
|
153
|
+
8. Do not put API keys in generated snippets. Use environment variables and keep
|
|
154
|
+
provider calls on the server.
|
|
155
|
+
|
|
156
|
+
OpenAI example:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import OpenAI from 'openai';
|
|
160
|
+
import { createPromptOpsKit } from 'promptopskit';
|
|
161
|
+
|
|
162
|
+
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
163
|
+
const kit = createPromptOpsKit({
|
|
164
|
+
sourceDir: './prompts',
|
|
165
|
+
compiledDir: './.generated-prompts/json',
|
|
166
|
+
mode: 'auto',
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const result = await kit.renderPrompt({
|
|
170
|
+
path: 'support/triage-summary',
|
|
171
|
+
provider: 'openai',
|
|
172
|
+
variables: {
|
|
173
|
+
ticket: ticketText,
|
|
174
|
+
},
|
|
175
|
+
strict: true,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
if (result.returnMessage) {
|
|
179
|
+
return result.returnMessage;
|
|
180
|
+
}
|
|
181
|
+
if (!result.request) {
|
|
182
|
+
throw new Error('Prompt rendering did not produce an OpenAI request.');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const completion = await client.chat.completions.create(result.request.body as any);
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Anthropic example:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
192
|
+
import { createPromptOpsKit } from 'promptopskit';
|
|
193
|
+
|
|
194
|
+
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
195
|
+
const kit = createPromptOpsKit({ sourceDir: './prompts' });
|
|
196
|
+
|
|
197
|
+
const result = await kit.renderPrompt({
|
|
198
|
+
path: 'support/triage-summary',
|
|
199
|
+
provider: 'anthropic',
|
|
200
|
+
variables: { ticket: ticketText },
|
|
201
|
+
strict: true,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
if (result.returnMessage) return result.returnMessage;
|
|
205
|
+
if (!result.request) throw new Error('Prompt rendering did not produce an Anthropic request.');
|
|
206
|
+
|
|
207
|
+
const message = await client.messages.create(result.request.body as any);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Google Gemini example:
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import { GoogleGenAI } from '@google/genai';
|
|
214
|
+
import { createPromptOpsKit } from 'promptopskit';
|
|
215
|
+
|
|
216
|
+
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
|
|
217
|
+
const kit = createPromptOpsKit({ sourceDir: './prompts' });
|
|
218
|
+
|
|
219
|
+
const result = await kit.renderPrompt({
|
|
220
|
+
path: 'support/triage-summary',
|
|
221
|
+
provider: 'gemini',
|
|
222
|
+
variables: { ticket: ticketText },
|
|
223
|
+
strict: true,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
if (result.returnMessage) return result.returnMessage;
|
|
227
|
+
if (!result.request) throw new Error('Prompt rendering did not produce a Gemini request.');
|
|
228
|
+
|
|
229
|
+
const response = await ai.models.generateContent({
|
|
230
|
+
model: result.request.model,
|
|
231
|
+
...(result.request.body as Record<string, unknown>),
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
OpenRouter example:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import OpenAI from 'openai';
|
|
239
|
+
import { createPromptOpsKit } from 'promptopskit';
|
|
240
|
+
|
|
241
|
+
const client = new OpenAI({
|
|
242
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
243
|
+
baseURL: 'https://openrouter.ai/api/v1',
|
|
244
|
+
});
|
|
245
|
+
const kit = createPromptOpsKit({ sourceDir: './prompts' });
|
|
246
|
+
|
|
247
|
+
const result = await kit.renderPrompt({
|
|
248
|
+
path: 'support/triage-summary',
|
|
249
|
+
provider: 'openrouter',
|
|
250
|
+
variables: { ticket: ticketText },
|
|
251
|
+
strict: true,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
if (result.returnMessage) return result.returnMessage;
|
|
255
|
+
if (!result.request) throw new Error('Prompt rendering did not produce an OpenRouter request.');
|
|
256
|
+
|
|
257
|
+
const completion = await client.chat.completions.create(result.request.body as any);
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
LLMAsAService example:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import OpenAI from 'openai';
|
|
264
|
+
import {
|
|
265
|
+
createLLMAsAServiceOpenAIConfig,
|
|
266
|
+
llmasaserviceAdapter,
|
|
267
|
+
} from 'promptopskit/llmasaservice';
|
|
268
|
+
|
|
269
|
+
const client = new OpenAI(createLLMAsAServiceOpenAIConfig({
|
|
270
|
+
baseURL: process.env.LLM_GATEWAY_BASE_URL,
|
|
271
|
+
projectId: process.env.LLM_GATEWAY_PROJECT_ID,
|
|
272
|
+
}));
|
|
273
|
+
|
|
274
|
+
const result = await llmasaserviceAdapter.renderPrompt(
|
|
275
|
+
{
|
|
276
|
+
path: 'support/triage-summary',
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
runtime: {
|
|
280
|
+
provider_options: {
|
|
281
|
+
llmasaservice: {
|
|
282
|
+
project_id: process.env.LLM_GATEWAY_PROJECT_ID,
|
|
283
|
+
customer: {
|
|
284
|
+
customer_id: customer.id,
|
|
285
|
+
customer_name: customer.name,
|
|
286
|
+
customer_user_id: user.id,
|
|
287
|
+
customer_user_email: user.email,
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
variables: { ticket: ticketText },
|
|
293
|
+
strict: true,
|
|
294
|
+
},
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
if (result.returnMessage) return result.returnMessage;
|
|
298
|
+
if (!('body' in result)) {
|
|
299
|
+
throw new Error('Prompt rendering did not produce an LLMAsAService request.');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const completion = await client.chat.completions.create(result.body as any);
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
If the user asks for "just the body", render with `kit.renderPrompt()` and show
|
|
306
|
+
or return `result.request.body`, not the whole render result.
|
|
307
|
+
|
|
308
|
+
### Other useful promptopskit request examples
|
|
309
|
+
|
|
310
|
+
Handle these common requests with the same conventions:
|
|
311
|
+
|
|
312
|
+
- "Add defaults for this prompt folder" -> create or update `defaults.md` with
|
|
313
|
+
shared `provider`, `model`, `metadata`, cache settings, and optional fallback
|
|
314
|
+
`# System instructions`.
|
|
315
|
+
- "Add inputs to this prompt" -> add exact `context.inputs` entries for every
|
|
316
|
+
placeholder and choose validation controls for risky or large values.
|
|
317
|
+
- "Make this prompt return JSON" -> add `response.format: json`,
|
|
318
|
+
`response.schema_name`, and a strict `response.schema`.
|
|
319
|
+
- "Add a test for this prompt" -> create a sidecar `.test.yaml` with realistic
|
|
320
|
+
`cases` and `variables`.
|
|
321
|
+
- "Compile/render/inspect/validate my prompts" -> use the matching
|
|
322
|
+
`promptopskit` CLI command and report validation errors with file references.
|
|
323
|
+
- "Move common instructions into a reusable prompt" -> create a shared fragment
|
|
324
|
+
and reference it with `includes`.
|
|
325
|
+
- "Add provider-specific options" -> prefer portable fields first, then
|
|
326
|
+
`provider_options`, and use `raw` only for unmodeled vendor fields with a note.
|
|
327
|
+
- "Make this safe for production" -> add validation for untrusted inputs, keep API
|
|
328
|
+
calls server-side, validate before compile, and avoid committing generated
|
|
329
|
+
artifacts unless the project already does.
|
|
12
330
|
|
|
13
331
|
---
|
|
14
332
|
|
|
@@ -58,7 +376,7 @@ the fields required by that specific file:
|
|
|
58
376
|
| `id` | string | **yes** | Unique identifier for the prompt |
|
|
59
377
|
| `schema_version` | number | yes | Always `1` |
|
|
60
378
|
| `description` | string | no | Human-readable description |
|
|
61
|
-
| `provider` | enum | no | `openai`, `openai-responses`, `anthropic`, `google`, `gemini`, `openrouter`, or `any` |
|
|
379
|
+
| `provider` | enum | no | `openai`, `openai-responses`, `anthropic`, `google`, `gemini`, `openrouter`, `llmasaservice`, or `any` |
|
|
62
380
|
| `model` | string | no | Model identifier (e.g. `gpt-5.4`, `claude-sonnet-4-20250514`) |
|
|
63
381
|
| `fallback_models` | string[] | no | Ordered fallback model list |
|
|
64
382
|
| `reasoning` | object | no | `{ effort: low|medium|high, budget_tokens: number }` |
|
|
@@ -66,11 +384,11 @@ the fields required by that specific file:
|
|
|
66
384
|
| `response` | object | no | `{ format: text|json|markdown, stream: boolean, schema?: object, schema_name?: string, schema_description?: string, schema_strict?: boolean }` |
|
|
67
385
|
| `cache` | object | no | Provider-specific cache controls (`openai`, `anthropic`, `gemini`/`google`) |
|
|
68
386
|
| `tools` | array | no | Tool names (strings) or inline definitions with `{ name, description, input_schema }` |
|
|
69
|
-
| `provider_options` | object | no | Provider-specific advanced options (`anthropic`, `gemini`, `openrouter`) |
|
|
387
|
+
| `provider_options` | object | no | Provider-specific advanced options (`anthropic`, `gemini`, `openrouter`, `llmasaservice`) |
|
|
70
388
|
| `raw` | object | no | Provider-scoped request-body passthrough for unmodeled vendor fields |
|
|
71
389
|
| `mcp` | object | no | `{ servers: [string | { name, config }] }` |
|
|
72
390
|
| `context.inputs` | `Array<string | { name, max_size?, trim?, allow_regex?, deny_regex?, non_empty?, reject_secrets? }>` | no | Declared variable names used in templates, with optional size budgets and runtime hardening controls |
|
|
73
|
-
| `context.history` | object | no | `{ max_items: number }
|
|
391
|
+
| `context.history` | object | no | `{ max_items: number }`; caps rendered history by compacting older turns into one preserved message |
|
|
74
392
|
| `includes` | string[] | no | Relative paths to other prompt files to include |
|
|
75
393
|
| `environments` | object | no | Per-environment overrides (see Overrides) |
|
|
76
394
|
| `tiers` | object | no | Per-tier overrides (see Overrides) |
|
|
@@ -131,6 +449,32 @@ If a validator declares `return_message`, `renderPrompt()` returns that message
|
|
|
131
449
|
|
|
132
450
|
Malformed `allow_regex` and `deny_regex` values fail during `validate` and `compile`, not just at render time. When regex compilation fails, the error includes the prompt id, variable name, field name, and raw configured value. Double-quoted YAML regex strings with raw backslashes fail as `POK013`; use `/pattern/i`, single-quoted `pattern: '...'`, or doubled backslashes.
|
|
133
451
|
|
|
452
|
+
### Conversation history limits
|
|
453
|
+
|
|
454
|
+
Use `context.history.max_items` when a chat-style prompt should bound rendered conversation history:
|
|
455
|
+
|
|
456
|
+
```yaml
|
|
457
|
+
context:
|
|
458
|
+
history:
|
|
459
|
+
max_items: 10
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
When runtime `history` exceeds `max_items`, PromptOpsKit preserves history by compacting older turns into one synthetic history message and keeping the most recent turns. Callers can provide `onHistoryCompaction` to create a custom summary:
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
const result = await kit.renderPrompt({
|
|
466
|
+
path: 'support/reply',
|
|
467
|
+
provider: 'openai',
|
|
468
|
+
history,
|
|
469
|
+
onHistoryCompaction: ({ overflow }) => ({
|
|
470
|
+
role: 'user',
|
|
471
|
+
content: `Earlier conversation summary: ${summarizeConversationUsingLLM(overflow)}`,
|
|
472
|
+
}),
|
|
473
|
+
});
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
If no callback is supplied, PromptOpsKit creates a plain text compacted history message. Do not describe `max_items` as dropping history; it preserves overflow through compaction.
|
|
477
|
+
|
|
134
478
|
Example: this is the minimal valid shape for a prompt that references
|
|
135
479
|
`{{ pull_request }}` even when provider/model are inherited from defaults:
|
|
136
480
|
|
|
@@ -250,7 +594,7 @@ Prefer portable fields first:
|
|
|
250
594
|
- Use `cache` for provider cache hints
|
|
251
595
|
- Use `tools` for tool definitions
|
|
252
596
|
|
|
253
|
-
Treat `response.schema` as the provider-neutral JSON Schema contract. The adapters emit it through provider-specific request fields: OpenAI/OpenRouter `response_format`, OpenAI Responses `text.format`, Anthropic `output_config.format`, and Gemini `generationConfig.responseJsonSchema`.
|
|
597
|
+
Treat `response.schema` as the provider-neutral JSON Schema contract. The adapters emit it through provider-specific request fields: OpenAI/OpenRouter/LLMAsAService `response_format`, OpenAI Responses `text.format`, Anthropic `output_config.format`, and Gemini `generationConfig.responseJsonSchema`.
|
|
254
598
|
|
|
255
599
|
Use `provider_options` for known non-portable mappings:
|
|
256
600
|
|
|
@@ -275,8 +619,16 @@ provider_options:
|
|
|
275
619
|
provider:
|
|
276
620
|
order: ["anthropic", "openai"]
|
|
277
621
|
transforms: ["middle-out"]
|
|
622
|
+
llmasaservice:
|
|
623
|
+
project_id: llm-project-id
|
|
624
|
+
# Optional default; usually pass the real customer at render time.
|
|
625
|
+
customer:
|
|
626
|
+
customer_id: cust_123
|
|
627
|
+
customer_name: Acme
|
|
278
628
|
```
|
|
279
629
|
|
|
630
|
+
For LLMAsAService, prefer putting the current customer/account/user attribution in `runtime.provider_options.llmasaservice.customer` during rendering. Static prompt metadata may include a default, but runtime values should override it for real requests.
|
|
631
|
+
|
|
280
632
|
Use `raw` only when a vendor request-body field is important and PromptOpsKit does not model it yet:
|
|
281
633
|
|
|
282
634
|
```yaml
|
|
@@ -292,9 +644,11 @@ raw:
|
|
|
292
644
|
openrouter:
|
|
293
645
|
usage:
|
|
294
646
|
include: true
|
|
647
|
+
llmasaservice:
|
|
648
|
+
conversationId: conv_123
|
|
295
649
|
```
|
|
296
650
|
|
|
297
|
-
Raw blocks are provider-scoped (`openai`, `openai-responses`/`openai_responses`, `anthropic`, `gemini`/`google`, `openrouter`) and are shallow-merged into the final request body after normalized fields. When adding `raw`, include a short note in `# Notes` explaining why a first-class field is not being used.
|
|
651
|
+
Raw blocks are provider-scoped (`openai`, `openai-responses`/`openai_responses`, `anthropic`, `gemini`/`google`, `openrouter`, `llmasaservice`) and are shallow-merged into the final request body after normalized fields. When adding `raw`, include a short note in `# Notes` explaining why a first-class field is not being used.
|
|
298
652
|
|
|
299
653
|
---
|
|
300
654
|
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {
|
|
2
|
+
openaiAdapter
|
|
3
|
+
} from "./chunk-D75HKF64.js";
|
|
4
|
+
import {
|
|
5
|
+
applyRawProviderBody,
|
|
6
|
+
resolveAssetForProvider,
|
|
7
|
+
withPromptInputSupport
|
|
8
|
+
} from "./chunk-KN7H4JRK.js";
|
|
9
|
+
|
|
10
|
+
// src/providers/llmasaservice.ts
|
|
11
|
+
var LLMASASERVICE_BASE_URL = "https://gateway.llmasaservice.io";
|
|
12
|
+
var LLMASASERVICE_SDK_PLACEHOLDER_API_KEY = "not-used-by-llm-gateway";
|
|
13
|
+
var LLMASASERVICE_DEFAULT_MODEL = "group:standard";
|
|
14
|
+
var LLMASASERVICE_RESPONSE_HEADER_NAMES = [
|
|
15
|
+
"x-request-id",
|
|
16
|
+
"x-llm-model-id",
|
|
17
|
+
"x-llm-model-group"
|
|
18
|
+
];
|
|
19
|
+
function createLLMAsAServiceOpenAIConfig(options = {}) {
|
|
20
|
+
return {
|
|
21
|
+
baseURL: options.baseURL ?? LLMASASERVICE_BASE_URL,
|
|
22
|
+
apiKey: LLMASASERVICE_SDK_PLACEHOLDER_API_KEY,
|
|
23
|
+
defaultHeaders: {
|
|
24
|
+
"x-project-id": options.projectId ?? ""
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function isGPT5ModelSelector(model) {
|
|
29
|
+
if (!model) return false;
|
|
30
|
+
return model.split(/[|,]/).map((candidate) => candidate.trim()).some((candidate) => candidate.startsWith("gpt-5") || candidate.startsWith("openai:gpt-5"));
|
|
31
|
+
}
|
|
32
|
+
function defaultModel() {
|
|
33
|
+
return LLMASASERVICE_DEFAULT_MODEL;
|
|
34
|
+
}
|
|
35
|
+
function isRecord(value) {
|
|
36
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37
|
+
}
|
|
38
|
+
function rawCustomerId(asset) {
|
|
39
|
+
const customer = isRecord(asset.raw?.llmasaservice?.customer) ? asset.raw.llmasaservice.customer : void 0;
|
|
40
|
+
return customer?.customer_id;
|
|
41
|
+
}
|
|
42
|
+
function isGatewayRenderValidation(runtime) {
|
|
43
|
+
return runtime?.runtime !== void 0;
|
|
44
|
+
}
|
|
45
|
+
var llmasaserviceAdapter = withPromptInputSupport({
|
|
46
|
+
name: "llmasaservice",
|
|
47
|
+
validate(asset, runtime) {
|
|
48
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
49
|
+
const validation = openaiAdapter.validate(
|
|
50
|
+
{
|
|
51
|
+
...resolvedAsset,
|
|
52
|
+
model: resolvedAsset.model ?? defaultModel()
|
|
53
|
+
},
|
|
54
|
+
runtime
|
|
55
|
+
);
|
|
56
|
+
const warnings = validation.warnings.filter(
|
|
57
|
+
(warning) => warning !== "OpenAI adapter requires a model to be specified."
|
|
58
|
+
);
|
|
59
|
+
const errors = [...validation.errors];
|
|
60
|
+
const gatewayOptions = resolvedAsset.provider_options?.llmasaservice;
|
|
61
|
+
const missingProjectId = !gatewayOptions?.project_id;
|
|
62
|
+
const missingCustomerId = !gatewayOptions?.customer?.customer_id && typeof rawCustomerId(resolvedAsset) !== "string";
|
|
63
|
+
const validateRenderMetadata = isGatewayRenderValidation(runtime);
|
|
64
|
+
if (missingProjectId && validateRenderMetadata) {
|
|
65
|
+
errors.push(
|
|
66
|
+
"LLMAsAService adapter requires provider_options.llmasaservice.project_id for x-project-id routing."
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (missingCustomerId && validateRenderMetadata) {
|
|
70
|
+
errors.push(
|
|
71
|
+
"LLMAsAService adapter requires customer.customer_id in provider_options.llmasaservice.customer or raw.llmasaservice.customer."
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if ((missingProjectId || missingCustomerId) && !validateRenderMetadata) {
|
|
75
|
+
warnings.push(
|
|
76
|
+
"LLMAsAService project_id and customer.customer_id must be supplied before rendering, usually through runtime provider_options."
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
valid: errors.length === 0,
|
|
81
|
+
errors,
|
|
82
|
+
warnings
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
render(asset, runtime) {
|
|
86
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
87
|
+
const options = resolvedAsset.provider_options?.llmasaservice;
|
|
88
|
+
const model = resolvedAsset.model ?? defaultModel();
|
|
89
|
+
const result = openaiAdapter.render(
|
|
90
|
+
{ ...resolvedAsset, model, raw: void 0 },
|
|
91
|
+
{
|
|
92
|
+
variables: runtime.variables,
|
|
93
|
+
history: runtime.history,
|
|
94
|
+
onHistoryCompaction: runtime.onHistoryCompaction,
|
|
95
|
+
toolRegistry: runtime.toolRegistry,
|
|
96
|
+
strict: runtime.strict
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
let body = { ...result.body };
|
|
100
|
+
if (isGPT5ModelSelector(model) && body.max_tokens !== void 0 && body.max_completion_tokens === void 0) {
|
|
101
|
+
body.max_completion_tokens = body.max_tokens;
|
|
102
|
+
delete body.max_tokens;
|
|
103
|
+
}
|
|
104
|
+
if (options?.customer !== void 0) body.customer = options.customer;
|
|
105
|
+
if (options?.conversationId !== void 0) body.conversationId = options.conversationId;
|
|
106
|
+
if (options?.conversationTitle !== void 0) body.conversationTitle = options.conversationTitle;
|
|
107
|
+
if (options?.projectId !== void 0) body.projectId = options.projectId;
|
|
108
|
+
body = applyRawProviderBody(body, resolvedAsset, "llmasaservice");
|
|
109
|
+
const projectId = options?.project_id ?? "";
|
|
110
|
+
return {
|
|
111
|
+
body,
|
|
112
|
+
provider: "llmasaservice",
|
|
113
|
+
model,
|
|
114
|
+
baseURL: options?.base_url ?? LLMASASERVICE_BASE_URL,
|
|
115
|
+
headers: {
|
|
116
|
+
"x-project-id": projectId
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
export {
|
|
123
|
+
LLMASASERVICE_BASE_URL,
|
|
124
|
+
LLMASASERVICE_SDK_PLACEHOLDER_API_KEY,
|
|
125
|
+
LLMASASERVICE_DEFAULT_MODEL,
|
|
126
|
+
LLMASASERVICE_RESPONSE_HEADER_NAMES,
|
|
127
|
+
createLLMAsAServiceOpenAIConfig,
|
|
128
|
+
llmasaserviceAdapter
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=chunk-6BOUQVSX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/llmasaservice.ts"],"sourcesContent":["import { openaiAdapter } from './openai.js';\nimport type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderRequest,\n RuntimeRenderOptions,\n ValidationResult,\n} from './types.js';\nimport { applyRawProviderBody } from './raw.js';\nimport { resolveAssetForProvider } from './resolve-asset.js';\nimport { withPromptInputSupport } from './prompt-input.js';\n\nexport const LLMASASERVICE_BASE_URL = 'https://gateway.llmasaservice.io';\nexport const LLMASASERVICE_SDK_PLACEHOLDER_API_KEY = 'not-used-by-llm-gateway';\nexport const LLMASASERVICE_DEFAULT_MODEL = 'group:standard';\nexport const LLMASASERVICE_RESPONSE_HEADER_NAMES = [\n 'x-request-id',\n 'x-llm-model-id',\n 'x-llm-model-group',\n] as const;\n\nexport interface LLMAsAServiceOpenAIConfig {\n baseURL: string;\n apiKey: string;\n defaultHeaders: {\n 'x-project-id': string;\n };\n}\n\nexport interface LLMAsAServiceOpenAIConfigOptions {\n baseURL?: string;\n projectId?: string;\n}\n\nexport function createLLMAsAServiceOpenAIConfig(\n options: LLMAsAServiceOpenAIConfigOptions = {},\n): LLMAsAServiceOpenAIConfig {\n return {\n baseURL: options.baseURL ?? LLMASASERVICE_BASE_URL,\n apiKey: LLMASASERVICE_SDK_PLACEHOLDER_API_KEY,\n defaultHeaders: {\n 'x-project-id': options.projectId ?? '',\n },\n };\n}\n\nfunction isGPT5ModelSelector(model: string | undefined): boolean {\n if (!model) return false;\n return model\n .split(/[|,]/)\n .map((candidate) => candidate.trim())\n .some((candidate) => candidate.startsWith('gpt-5') || candidate.startsWith('openai:gpt-5'));\n}\n\nfunction defaultModel(): string {\n return LLMASASERVICE_DEFAULT_MODEL;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction rawCustomerId(asset: ResolvedPromptAsset): unknown {\n const customer = isRecord(asset.raw?.llmasaservice?.customer)\n ? asset.raw.llmasaservice.customer\n : undefined;\n return customer?.customer_id;\n}\n\nfunction isGatewayRenderValidation(runtime: RuntimeRenderOptions | undefined): boolean {\n return runtime?.runtime !== undefined;\n}\n\n/**\n * LLMAsAService gateway adapter.\n * Uses the OpenAI Chat Completions body shape, plus gateway routing and\n * attribution fields supported by gateway.llmasaservice.io.\n */\nexport const llmasaserviceAdapter: ProviderAdapter = withPromptInputSupport({\n name: 'llmasaservice',\n\n validate(asset: ResolvedPromptAsset, runtime?: RuntimeRenderOptions): ValidationResult {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const validation = openaiAdapter.validate(\n {\n ...resolvedAsset,\n model: resolvedAsset.model ?? defaultModel(),\n },\n runtime,\n );\n const warnings = validation.warnings.filter(\n (warning) => warning !== 'OpenAI adapter requires a model to be specified.',\n );\n\n const errors = [...validation.errors];\n const gatewayOptions = resolvedAsset.provider_options?.llmasaservice;\n const missingProjectId = !gatewayOptions?.project_id;\n const missingCustomerId =\n !gatewayOptions?.customer?.customer_id && typeof rawCustomerId(resolvedAsset) !== 'string';\n const validateRenderMetadata = isGatewayRenderValidation(runtime);\n\n if (missingProjectId && validateRenderMetadata) {\n errors.push(\n 'LLMAsAService adapter requires provider_options.llmasaservice.project_id for x-project-id routing.',\n );\n }\n\n if (missingCustomerId && validateRenderMetadata) {\n errors.push(\n 'LLMAsAService adapter requires customer.customer_id in provider_options.llmasaservice.customer or raw.llmasaservice.customer.',\n );\n }\n\n if ((missingProjectId || missingCustomerId) && !validateRenderMetadata) {\n warnings.push(\n 'LLMAsAService project_id and customer.customer_id must be supplied before rendering, usually through runtime provider_options.',\n );\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n },\n\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const options = resolvedAsset.provider_options?.llmasaservice;\n const model = resolvedAsset.model ?? defaultModel();\n const result = openaiAdapter.render(\n { ...resolvedAsset, model, raw: undefined },\n {\n variables: runtime.variables,\n history: runtime.history,\n onHistoryCompaction: runtime.onHistoryCompaction,\n toolRegistry: runtime.toolRegistry,\n strict: runtime.strict,\n },\n );\n let body = { ...result.body };\n\n if (isGPT5ModelSelector(model) && body.max_tokens !== undefined && body.max_completion_tokens === undefined) {\n body.max_completion_tokens = body.max_tokens;\n delete body.max_tokens;\n }\n\n if (options?.customer !== undefined) body.customer = options.customer;\n if (options?.conversationId !== undefined) body.conversationId = options.conversationId;\n if (options?.conversationTitle !== undefined) body.conversationTitle = options.conversationTitle;\n if (options?.projectId !== undefined) body.projectId = options.projectId;\n\n body = applyRawProviderBody(body, resolvedAsset, 'llmasaservice');\n\n const projectId = options?.project_id ?? '';\n\n return {\n body,\n provider: 'llmasaservice',\n model,\n baseURL: options?.base_url ?? LLMASASERVICE_BASE_URL,\n headers: {\n 'x-project-id': projectId,\n },\n };\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyRawProviderBody,
|
|
3
|
+
compactHistoryForPrompt,
|
|
3
4
|
renderSections,
|
|
4
5
|
resolveAssetForProvider,
|
|
5
6
|
withPromptInputSupport
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-KN7H4JRK.js";
|
|
7
8
|
|
|
8
9
|
// src/providers/openai-responses.ts
|
|
9
10
|
var openaiResponsesAdapter = withPromptInputSupport({
|
|
@@ -34,8 +35,9 @@ var openaiResponsesAdapter = withPromptInputSupport({
|
|
|
34
35
|
});
|
|
35
36
|
const responseOptions = runtime.openaiResponses;
|
|
36
37
|
const input = [];
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
const history = compactHistoryForPrompt(resolvedAsset, runtime);
|
|
39
|
+
if (history) {
|
|
40
|
+
for (const msg of history) {
|
|
39
41
|
input.push({ role: msg.role, content: msg.content });
|
|
40
42
|
}
|
|
41
43
|
}
|
|
@@ -110,4 +112,4 @@ var openaiResponsesAdapter = withPromptInputSupport({
|
|
|
110
112
|
export {
|
|
111
113
|
openaiResponsesAdapter
|
|
112
114
|
};
|
|
113
|
-
//# sourceMappingURL=chunk-
|
|
115
|
+
//# sourceMappingURL=chunk-6VLKZCNS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/openai-responses.ts"],"sourcesContent":["import type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} from './types.js';\nimport { renderSections } from '../renderer/index.js';\nimport { resolveAssetForProvider } from './resolve-asset.js';\nimport { withPromptInputSupport } from './prompt-input.js';\nimport { applyRawProviderBody } from './raw.js';\nimport { compactHistoryForPrompt } from '../history.js';\n\n/**\n * OpenAI Responses provider adapter.\n * Produces request bodies compatible with the OpenAI Responses API.\n */\nexport const openaiResponsesAdapter: ProviderAdapter = withPromptInputSupport({\n name: 'openai-responses',\n\n validate(asset: ResolvedPromptAsset, runtime?: RuntimeRenderOptions): ValidationResult {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!resolvedAsset.model) {\n errors.push('OpenAI Responses adapter requires a model to be specified.');\n }\n\n if (resolvedAsset.reasoning?.budget_tokens !== undefined) {\n warnings.push('OpenAI Responses uses reasoning.effort, not budget_tokens. budget_tokens will be ignored.');\n }\n\n if (resolvedAsset.response?.schema !== undefined && resolvedAsset.response?.format !== 'json') {\n warnings.push('OpenAI Responses response.schema requires response.format: json. schema will still be applied as JSON schema output.');\n }\n\n if (runtime?.openaiResponses?.conversation !== undefined && runtime?.openaiResponses?.previous_response_id !== undefined) {\n errors.push('OpenAI Responses options \"conversation\" and \"previous_response_id\" cannot both be set.');\n }\n\n return { valid: errors.length === 0, errors, warnings };\n },\n\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const sections = renderSections(resolvedAsset, {\n variables: runtime.variables,\n strict: runtime.strict,\n });\n const responseOptions = runtime.openaiResponses;\n\n const input: Array<Record<string, unknown>> = [];\n\n const history = compactHistoryForPrompt(resolvedAsset, runtime);\n if (history) {\n for (const msg of history) {\n input.push({ role: msg.role, content: msg.content });\n }\n }\n\n if (sections.prompt_template) {\n input.push({ role: 'user', content: sections.prompt_template });\n }\n\n const body: Record<string, unknown> = {\n model: resolvedAsset.model,\n input,\n };\n\n if (responseOptions?.instructions !== undefined) {\n body.instructions = responseOptions.instructions;\n } else if (sections.system_instructions) {\n body.instructions = sections.system_instructions;\n }\n\n // Sampling params\n if (resolvedAsset.sampling?.temperature !== undefined) body.temperature = resolvedAsset.sampling.temperature;\n if (resolvedAsset.sampling?.top_p !== undefined) body.top_p = resolvedAsset.sampling.top_p;\n if (resolvedAsset.sampling?.frequency_penalty !== undefined) body.frequency_penalty = resolvedAsset.sampling.frequency_penalty;\n if (resolvedAsset.sampling?.presence_penalty !== undefined) body.presence_penalty = resolvedAsset.sampling.presence_penalty;\n if (resolvedAsset.sampling?.stop !== undefined) body.stop = resolvedAsset.sampling.stop;\n if (resolvedAsset.sampling?.max_output_tokens !== undefined) body.max_output_tokens = resolvedAsset.sampling.max_output_tokens;\n\n // Reasoning\n if (resolvedAsset.reasoning?.effort) {\n body.reasoning = { effort: resolvedAsset.reasoning.effort };\n }\n\n // Structured output / response format\n if (resolvedAsset.response?.schema) {\n body.text = {\n format: {\n type: 'json_schema',\n name: resolvedAsset.response.schema_name ?? `${resolvedAsset.id}_response`,\n ...(resolvedAsset.response.schema_description ? { description: resolvedAsset.response.schema_description } : {}),\n schema: resolvedAsset.response.schema,\n strict: resolvedAsset.response.schema_strict ?? true,\n },\n };\n } else if (resolvedAsset.response?.format === 'json') {\n body.text = { format: { type: 'json_object' } };\n }\n\n // Streaming\n if (resolvedAsset.response?.stream !== undefined) {\n body.stream = resolvedAsset.response.stream;\n }\n\n // Tools\n if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {\n body.tools = resolvedAsset.tools.map((tool) => {\n if (typeof tool === 'string') {\n const def = runtime.toolRegistry?.[tool];\n if (def) return def;\n return { type: 'function', name: tool };\n }\n return {\n type: 'function',\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n };\n });\n }\n\n if (responseOptions?.previous_response_id !== undefined) body.previous_response_id = responseOptions.previous_response_id;\n if (responseOptions?.conversation !== undefined) body.conversation = responseOptions.conversation;\n if (responseOptions?.parallel_tool_calls !== undefined) body.parallel_tool_calls = responseOptions.parallel_tool_calls;\n if (responseOptions?.max_tool_calls !== undefined) body.max_tool_calls = responseOptions.max_tool_calls;\n if (responseOptions?.store !== undefined) body.store = responseOptions.store;\n if (responseOptions?.metadata !== undefined) body.metadata = responseOptions.metadata;\n if (responseOptions?.include !== undefined) body.include = responseOptions.include;\n if (responseOptions?.background !== undefined) body.background = responseOptions.background;\n\n return {\n body: applyRawProviderBody(body, resolvedAsset, 'openai-responses'),\n provider: 'openai-responses',\n model: resolvedAsset.model ?? 'unknown',\n };\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -273,7 +273,7 @@ function applyUsageTapEntitlements(request, begin, options = {}) {
|
|
|
273
273
|
if (!isObject2(nextRequest.body)) {
|
|
274
274
|
return nextRequest;
|
|
275
275
|
}
|
|
276
|
-
if (nextRequest.provider === "openai" || nextRequest.provider === "openrouter") {
|
|
276
|
+
if (nextRequest.provider === "openai" || nextRequest.provider === "openrouter" || nextRequest.provider === "llmasaservice") {
|
|
277
277
|
capOpenAIReasoning(nextRequest.body, allowed);
|
|
278
278
|
if (isRecordArray(nextRequest.body.tools)) {
|
|
279
279
|
nextRequest.body.tools = filterOpenAITools(nextRequest.body.tools, allowed, options);
|
|
@@ -362,6 +362,9 @@ function runOpenAIWithUsageTap(client, options) {
|
|
|
362
362
|
function runOpenRouterWithUsageTap(client, options) {
|
|
363
363
|
return runProviderWithUsageTap(client, options, extractOpenAIUsage);
|
|
364
364
|
}
|
|
365
|
+
function runLLMAsAServiceWithUsageTap(client, options) {
|
|
366
|
+
return runProviderWithUsageTap(client, options, extractOpenAIUsage);
|
|
367
|
+
}
|
|
365
368
|
function runAnthropicWithUsageTap(client, options) {
|
|
366
369
|
return runProviderWithUsageTap(client, options, extractAnthropicUsage);
|
|
367
370
|
}
|
|
@@ -381,7 +384,8 @@ export {
|
|
|
381
384
|
extractGeminiUsage,
|
|
382
385
|
runOpenAIWithUsageTap,
|
|
383
386
|
runOpenRouterWithUsageTap,
|
|
387
|
+
runLLMAsAServiceWithUsageTap,
|
|
384
388
|
runAnthropicWithUsageTap,
|
|
385
389
|
runGeminiWithUsageTap
|
|
386
390
|
};
|
|
387
|
-
//# sourceMappingURL=chunk-
|
|
391
|
+
//# sourceMappingURL=chunk-AGTGIZMR.js.map
|