fix(api): reanchor substantial text boundaries

This commit is contained in:
Danny Avila 2026-08-13 07:44:37 -04:00
parent aa3b6c386c
commit c8080a09f7
2 changed files with 36 additions and 4 deletions

View file

@ -24,7 +24,9 @@ const batch = (id: string): PostToolBatchHookInput =>
],
}) as PostToolBatchHookInput;
const substantialText = (prefix: string): string => `${prefix} ${'x'.repeat(201)}`;
const SUBSTANTIAL_TEXT_CHARS = 200;
const substantialText = (prefix: string): string =>
`${prefix} ${'x'.repeat(SUBSTANTIAL_TEXT_CHARS + 1)}`;
async function flushDetached(): Promise<void> {
for (let i = 0; i < 4; i += 1) {
@ -40,7 +42,7 @@ describe('createActivityPhaseWiring', () => {
const generatePhase = jest.fn(async () => ({ label: 'Resolved the release compatibility' }));
const wiring = createActivityPhaseWiring({
getContentParts: () => parts,
getStepIndex: (stepId) => (stepId === 'final-step' ? 2 : undefined),
getStepIndex: (stepId) => (stepId === 'final-step' ? 1 : undefined),
bumpIndexOffset: jest.fn(),
emitLabelEvent,
trackPendingFill: jest.fn(),
@ -96,7 +98,9 @@ describe('createActivityPhaseWiring', () => {
GraphEvents.ON_MESSAGE_DELTA,
{
id: 'final-step',
delta: { content: { type: ContentTypes.TEXT, text: 'A'.repeat(201) } },
delta: {
content: { type: ContentTypes.TEXT, text: 'A'.repeat(SUBSTANTIAL_TEXT_CHARS + 1) },
},
},
undefined,
undefined,

View file

@ -364,6 +364,27 @@ function findReasoningStart(
return startIndex ?? findLastPartIndex(parts, ContentTypes.THINK);
}
function findTextBoundary(
parts: ReadonlyArray<LooseContentPart | null | undefined>,
text: string,
stepIndex?: number,
): number | undefined {
const needle = text.trim().slice(-REASONING_ANCHOR_CHARS);
const matches = (part: LooseContentPart | null | undefined) =>
part?.type === ContentTypes.TEXT && textValue(part.text).includes(needle);
if (stepIndex != null && matches(parts[stepIndex])) {
return stepIndex;
}
const indices = definedPartIndices(parts);
for (let position = indices.length - 1; position >= 0; position -= 1) {
const index = indices[position];
if (matches(parts[index])) {
return index;
}
}
return undefined;
}
/** Persists Open Responses text-phase metadata onto LibreChat text parts.
* Installed for existing batch labels too, so commentary can supply intent
* even when parent phase summaries are disabled. */
@ -992,7 +1013,14 @@ export function createActivityPhaseWiring(deps: ActivityPhaseHostDeps): Activity
contextEntry.text = `${contextEntry.text}${text}`.slice(-MAX_EXCERPT_CHARS);
}
const result = messageHandler.handle(event, data, metadata, graph);
const boundaryIndex = id ? deps.getStepIndex?.(id) : undefined;
const boundaryIndex =
id && contextEntry != null
? findTextBoundary(
deps.getContentParts(),
contextEntry.text,
deps.getStepIndex?.(id),
)
: undefined;
if (
contextEntry != null &&
contextEntry.text.trim().length > SUBSTANTIAL_TEXT_CHARS &&