takt/src/faceted-prompting/truncation.ts
nrs 0d1da61d14
[draft] takt/284/implement-using-only-the-files (#296)
* feat: track project-level .takt/pieces in version control

* feat: track project-level takt facets for customizable resources

* chore: include project .takt/config.yaml in git-tracked subset

* takt: github-issue-284-faceted-prompting
2026-02-18 23:21:09 +09:00

89 lines
2.4 KiB
TypeScript

/**
* Context truncation for knowledge and policy facets.
*
* When facet content exceeds a character limit, it is trimmed and
* annotated with source-path metadata so the LLM can consult the
* original file.
*
* This module has ZERO dependencies on TAKT internals.
*/
interface PreparedContextBlock {
readonly content: string;
readonly truncated: boolean;
}
/**
* Trim content to a maximum character length, appending a
* "...TRUNCATED..." marker when truncation occurs.
*/
export function trimContextContent(
content: string,
maxChars: number,
): PreparedContextBlock {
if (content.length <= maxChars) {
return { content, truncated: false };
}
return {
content: `${content.slice(0, maxChars)}\n...TRUNCATED...`,
truncated: true,
};
}
/**
* Standard notice appended to knowledge and policy blocks.
*/
export function renderConflictNotice(): string {
return 'If prompt content conflicts with source files, source files take precedence.';
}
/**
* Prepare a knowledge facet for inclusion in a prompt.
*
* Trims to maxChars, appends truncation notice and source path if available.
*/
export function prepareKnowledgeContent(
content: string,
maxChars: number,
sourcePath?: string,
): string {
const prepared = trimContextContent(content, maxChars);
const lines: string[] = [prepared.content];
if (prepared.truncated && sourcePath) {
lines.push(
'',
`Knowledge is truncated. You MUST consult the source files before making decisions. Source: ${sourcePath}`,
);
}
if (sourcePath) {
lines.push('', `Knowledge Source: ${sourcePath}`);
}
lines.push('', renderConflictNotice());
return lines.join('\n');
}
/**
* Prepare a policy facet for inclusion in a prompt.
*
* Trims to maxChars, appends authoritative-source notice and source path if available.
*/
export function preparePolicyContent(
content: string,
maxChars: number,
sourcePath?: string,
): string {
const prepared = trimContextContent(content, maxChars);
const lines: string[] = [prepared.content];
if (prepared.truncated && sourcePath) {
lines.push(
'',
`Policy is authoritative. If truncated, you MUST read the full policy file and follow it strictly. Source: ${sourcePath}`,
);
}
if (sourcePath) {
lines.push('', `Policy Source: ${sourcePath}`);
}
lines.push('', renderConflictNotice());
return lines.join('\n');
}