Skip to content

Commit 9d28a9b

Browse files
Fix trim:false to disable runtime trimming
1 parent 71da240 commit 9d28a9b

4 files changed

Lines changed: 56 additions & 6 deletions

File tree

src/context.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ export function normalizeContextInput(input: ContextInputDefinition): Normalized
5858

5959
type TrimMode = boolean | 'start' | 'end' | 'both';
6060

61+
function isTrimEnabled(mode: TrimMode | undefined): mode is true | 'start' | 'end' | 'both' {
62+
return mode === true || mode === 'start' || mode === 'end' || mode === 'both';
63+
}
64+
6165
function normalizeTrimMode(mode: TrimMode): 'start' | 'end' {
6266
if (mode === 'start') {
6367
return 'start';
@@ -135,11 +139,8 @@ export function sanitizeContextVariables(
135139
}
136140
}
137141

138-
if (input.trim !== undefined) {
139-
const trimMode = input.trim;
140-
if (input.max_size !== undefined) {
141-
candidate = trimToMaxSize(candidate, input.max_size, trimMode);
142-
}
142+
if (isTrimEnabled(input.trim) && input.max_size !== undefined) {
143+
candidate = trimToMaxSize(candidate, input.max_size, input.trim);
143144
}
144145

145146
sanitized[input.name] = candidate;

src/validation/validate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export function validateAsset(
118118

119119
// Context regex definitions compile successfully
120120
for (const input of getContextInputs(asset)) {
121-
if (input.trim !== undefined && input.max_size === undefined) {
121+
if (input.trim !== undefined && input.trim !== false && input.max_size === undefined) {
122122
warnings.push({
123123
code: 'POK014',
124124
message: `Context input "${input.name}" sets trim but has no max_size; trim-to-budget will be skipped.`,

tests/runtime-context-placeholders.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,41 @@ Context: {{ app_context }}
338338
expect(result.warnings).toHaveLength(0);
339339
});
340340

341+
it('does not trim when trim is explicitly false and still emits oversize warning', async () => {
342+
const sourceDir = join(tmpDir, 'prompts');
343+
await mkdir(sourceDir, { recursive: true });
344+
345+
await writeFile(join(sourceDir, 'untrimmed-context.md'), `---
346+
id: untrimmed.context
347+
schema_version: 1
348+
provider: openai
349+
model: gpt-5.4
350+
context:
351+
inputs:
352+
- name: app_context
353+
trim: false
354+
max_size: 5
355+
---
356+
357+
# Prompt template
358+
359+
Context: {{ app_context }}
360+
`);
361+
362+
const kit = createPromptOpsKit({ sourceDir, mode: 'source-only', cache: false });
363+
const result = await kit.renderPrompt({
364+
path: 'untrimmed-context',
365+
provider: 'openai',
366+
variables: { app_context: 'admin-dashboard' },
367+
});
368+
369+
const messages = result.request.body.messages as Array<{ role: string; content: string }>;
370+
expect(messages[0].content).toContain('Context: admin-dashboard');
371+
expect(result.warnings).toContain(
372+
'POK030: Context variable "app_context" exceeded max_size for prompt "untrimmed.context" (15 bytes > 5 bytes).',
373+
);
374+
});
375+
341376
it('rejects context variables that fail regex validation', async () => {
342377
const sourceDir = join(tmpDir, 'prompts');
343378
await mkdir(sourceDir, { recursive: true });

tests/validation.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,20 @@ describe('validateAsset', () => {
138138
expect(result.warnings.some((warning) => warning.code === 'POK014')).toBe(true);
139139
});
140140

141+
it('does not warn when trim is explicitly false without max_size', () => {
142+
const result = validateAsset({
143+
id: 'test',
144+
schema_version: 1,
145+
context: {
146+
inputs: [{ name: 'user_id', trim: false }],
147+
},
148+
sections: { prompt_template: '{{ user_id }}' },
149+
});
150+
151+
expect(result.valid).toBe(true);
152+
expect(result.warnings.some((warning) => warning.code === 'POK014')).toBe(false);
153+
});
154+
141155
it('warns when regex and allow_regex are both set', () => {
142156
const result = validateAsset({
143157
id: 'test',

0 commit comments

Comments
 (0)