mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-29 07:13:44 +08:00
fix(ui): head a listed answer with the callers it lists
"Callers of JSONBAgg ... 23 incoming relationships from 12 symbols" was
followed by 11 callers. The heading now counts what it lists, "11 callers
(CALLS) of JSONBAgg in the loaded graph.", and gives all incoming
relationships apart ("All incoming: 23 relationships from 12 symbols.").
What a selection calls is a full sentence in both languages, the German
list of other types is headed "Andere", and a side that cannot be listed
says why in a full sentence. The K16 hand test expects the new heading.
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
This commit is contained in:
@@ -930,7 +930,7 @@ describe('graph answers and answer limits', () => {
|
||||
const last = () => [...container.querySelectorAll('.cbm-chat-turn')].at(-1)!;
|
||||
await type('wer ruf jsonbagg auf'); await click('Send ↑');
|
||||
expect(runtime.chat).not.toHaveBeenCalled();
|
||||
expect(last().querySelector('.cbm-chat-answer-text')?.textContent).toContain('Aufrufer von JSONBAgg im geladenen Graphen');
|
||||
expect(last().querySelector('.cbm-chat-answer-text')?.textContent).toContain('11 Aufrufer (CALLS) von JSONBAgg im geladenen Graphen.');
|
||||
expect([...last().querySelectorAll('button.cbm-chat-retry')].map(item => item.textContent)).toEqual(['Modell fragen']);
|
||||
await type('jsonbagg aufrufe?'); await click('Send ↑');
|
||||
expect(runtime.chat).not.toHaveBeenCalled();
|
||||
@@ -939,7 +939,7 @@ describe('graph answers and answer limits', () => {
|
||||
expect([...last().querySelectorAll('button.cbm-chat-retry')].map(item => item.textContent)).toEqual(['Liste anzeigen', 'Modell fragen']);
|
||||
await click('Liste anzeigen');
|
||||
expect(runtime.chat).not.toHaveBeenCalled();
|
||||
expect(last().querySelector('.cbm-chat-answer-text')?.textContent).toContain('Aufrufer von JSONBAgg im geladenen Graphen');
|
||||
expect(last().querySelector('.cbm-chat-answer-text')?.textContent).toContain('11 Aufrufer (CALLS) von JSONBAgg im geladenen Graphen.');
|
||||
for (const name of JSONB_AGG_CALLERS) expect(last().textContent).toContain(name);
|
||||
await type('jsonbagg calls'); await click('Send ↑');
|
||||
expect(last().querySelector('.cbm-chat-answer-text')?.textContent).toContain('Did you mean: what JSONBAgg calls?');
|
||||
|
||||
@@ -82,3 +82,43 @@ describe('relationship counts that read as counts, not as a score (W2)', () => {
|
||||
expect(selectionSummary(lonely, 'de').slice(1, 3)).toEqual(['Eingehend: keine Beziehungen in diesem Ausschnitt.', 'Ausgehend: keine Beziehungen in diesem Ausschnitt.']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('the heading of a listed caller or callee answer (W3)', () => {
|
||||
const answer = (prompt: string, context = jsonbAggEvidence()) => relationshipAnswer(prompt, [context])!.markdown;
|
||||
// Two callers of JSONBAgg with CALLS only, and three calls from it.
|
||||
const calling = () => jsonbAggEvidence({ edges: [{ source: 100, target: 32360, type: 'CALLS' }, { source: 101, target: 32360, type: 'CALLS' },
|
||||
{ source: 32360, target: 7, type: 'CALLS' }, { source: 32360, target: 8, type: 'CALLS' }, { source: 32360, target: 9, type: 'CALLS' }, { source: 32360, target: 7, type: 'INHERITS' }] });
|
||||
|
||||
it('counts the callers it lists and gives all incoming relationships as a sentence of their own', () => {
|
||||
expect(answer('Who calls JSONBAgg?').split('\n')[0]).toBe('11 callers (CALLS) of `JSONBAgg` in the loaded graph. All incoming: 23 relationships from 12 symbols.');
|
||||
expect(answer('Wer ruft JSONBAgg auf?').split('\n')[0]).toBe('11 Aufrufer (CALLS) von `JSONBAgg` im geladenen Graphen. Alle eingehenden: 23 Beziehungen von 12 Symbolen.');
|
||||
// With CALLS as the only type there is nothing more to count.
|
||||
expect(answer('Who calls JSONBAgg?', calling()).split('\n')[0]).toBe('2 callers (CALLS) of `JSONBAgg` in the loaded graph.');
|
||||
});
|
||||
|
||||
it('says what the selection calls as a full sentence, in English and German', () => {
|
||||
expect(answer('What does JSONBAgg call?', calling()).split('\n')[0])
|
||||
.toBe('`JSONBAgg` calls 3 symbols (CALLS) in the loaded graph. All outgoing: 4 relationships to 3 symbols.');
|
||||
expect(answer('Was ruft JSONBAgg auf?', calling()).split('\n')[0])
|
||||
.toBe('`JSONBAgg` ruft im geladenen Graphen 3 Symbole auf (CALLS). Alle ausgehenden: 4 Beziehungen zu 3 Symbolen.');
|
||||
expect(answer('Was ruft JSONBAgg auf?').split('\n')[0])
|
||||
.toBe('`JSONBAgg` hat in diesem Ausschnitt keine ausgehende CALLS-Kante. Ausgehend: 2 Beziehungen zu 2 Symbolen.');
|
||||
expect(answer('What does JSONBAgg call?').split('\n')[0])
|
||||
.toBe('`JSONBAgg` has no outgoing CALLS edge in this scope. Outgoing: 2 relationships to 2 symbols.');
|
||||
expect(answer('Was ruft JSONBAgg auf?')).not.toContain('Was `JSONBAgg` im geladenen Graphen aufruft.');
|
||||
});
|
||||
|
||||
it('heads the other edge types "Andere" in German, also right after "keine ausgehende CALLS-Kante"', () => {
|
||||
expect(answer('Was ruft JSONBAgg auf?')).toContain('\n\nAndere ausgehende Beziehungen:\n- **INHERITS (2):**');
|
||||
expect(answer('Wer ruft JSONBAgg auf?')).toContain('\n\nAndere eingehende Beziehungen:\n- **TESTS (11):**');
|
||||
expect(answer('What does JSONBAgg call?')).toContain('\n\nOther outgoing relationships:\n- **INHERITS (2):**');
|
||||
expect(answer('Wer ruft JSONBAgg auf?') + answer('Was ruft JSONBAgg auf?')).not.toContain('Weitere');
|
||||
});
|
||||
|
||||
it('says in a full sentence why nothing is listed', () => {
|
||||
expect(answer('Who calls JSONBAgg?', jsonbAggEvidence({ direction: 'outbound' })).split('\n')[0]).toMatch(/^The callers of `JSONBAgg` cannot be listed from this scope\. /);
|
||||
expect(answer('Was ruft JSONBAgg auf?', jsonbAggEvidence({ direction: 'inbound' })).split('\n')[0]).toMatch(/^Was `JSONBAgg` aufruft, lässt sich aus diesem Ausschnitt nicht auflisten\. /);
|
||||
expect(answer('Who calls JSONBAgg?', jsonbAggEvidence({ edges: [] })).split('\n')[0]).toBe('`JSONBAgg` has no callers and no other incoming relationships in this scope.');
|
||||
expect(answer('Was ruft JSONBAgg auf?', jsonbAggEvidence({ edges: [] })).split('\n')[0]).toBe('`JSONBAgg` ruft in diesem Ausschnitt nichts auf und hat keine anderen ausgehenden Beziehungen.');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,10 @@ import { JSONB_AGG_CALLERS, jsonbAggEvidence, jsonbAggRenderLimited, largeFolder
|
||||
import { correctRelationWords, relationshipAnswer, relationshipQuestion, relationshipSuggestion } from './relationship-answer';
|
||||
|
||||
const line = (markdown: string, type: string) => markdown.split('\n').find(item => item.startsWith(`- **${type} (`)) ?? '';
|
||||
/** How a listed answer about JSONBAgg begins: its callers, or that it calls nothing (it only inherits). */
|
||||
const heading = (side: 'incoming' | 'outgoing', language: 'en' | 'de') => side === 'incoming'
|
||||
? language === 'de' ? '11 Aufrufer (CALLS) von `JSONBAgg` im geladenen Graphen.' : '11 callers (CALLS) of `JSONBAgg` in the loaded graph.'
|
||||
: language === 'de' ? '`JSONBAgg` hat in diesem Ausschnitt keine ausgehende CALLS-Kante.' : '`JSONBAgg` has no outgoing CALLS edge in this scope.';
|
||||
|
||||
describe('caller and callee questions', () => {
|
||||
it.each([
|
||||
@@ -49,7 +53,7 @@ describe('caller and callee questions', () => {
|
||||
describe('listed relationship answers', () => {
|
||||
it('lists the callers first with their count and every other incoming relationship under its own heading (C2)', () => {
|
||||
const answer = relationshipAnswer('Who calls JSONBAgg? List every caller and the edge type.', [jsonbAggEvidence()])!;
|
||||
expect(answer.markdown).toContain('Callers of `JSONBAgg` in the loaded graph. 23 incoming relationships from 12 symbols.');
|
||||
expect(answer.markdown).toContain('11 callers (CALLS) of `JSONBAgg` in the loaded graph. All incoming: 23 relationships from 12 symbols.');
|
||||
const calls = line(answer.markdown, 'CALLS'), tests = line(answer.markdown, 'TESTS');
|
||||
// TESTS and DEFINES are no callers: they follow under their own heading.
|
||||
expect(answer.markdown.indexOf(calls)).toBeLessThan(answer.markdown.indexOf('Other incoming relationships:'));
|
||||
@@ -70,7 +74,7 @@ describe('listed relationship answers', () => {
|
||||
|
||||
it('answers callee questions with the outgoing side only and says when no CALLS edge exists', () => {
|
||||
const answer = relationshipAnswer('What does JSONBAgg call?', [jsonbAggEvidence()])!;
|
||||
expect(answer.markdown).toContain('What `JSONBAgg` calls in the loaded graph. 2 outgoing relationships to 2 symbols.');
|
||||
expect(answer.markdown).toContain('`JSONBAgg` has no outgoing CALLS edge in this scope. Outgoing: 2 relationships to 2 symbols.');
|
||||
expect(answer.markdown).toContain('`JSONBAgg` has no outgoing CALLS edge in this scope.');
|
||||
expect(answer.markdown).toContain('Other outgoing relationships:');
|
||||
expect(line(answer.markdown, 'INHERITS')).toMatch(/^- \*\*INHERITS \(2\):\*\* `OrderableAggMixin`.*`Aggregate`/);
|
||||
@@ -79,15 +83,15 @@ describe('listed relationship answers', () => {
|
||||
|
||||
it('answers in German for a German question', () => {
|
||||
const answer = relationshipAnswer('Wer ruft JSONBAgg auf?', [jsonbAggEvidence()])!;
|
||||
expect(answer.markdown).toContain('Aufrufer von `JSONBAgg` im geladenen Graphen. 23 eingehende Beziehungen aus 12 Symbolen.');
|
||||
expect(answer.markdown).toContain('11 Aufrufer (CALLS) von `JSONBAgg` im geladenen Graphen. Alle eingehenden: 23 Beziehungen von 12 Symbolen.');
|
||||
expect(line(answer.markdown, 'CALLS')).toMatch(/^- \*\*CALLS \(11\):\*\* `test_default_argument`/);
|
||||
expect(answer.markdown.indexOf('Weitere eingehende Beziehungen:')).toBeGreaterThan(answer.markdown.indexOf(line(answer.markdown, 'CALLS')));
|
||||
expect(answer.markdown.indexOf('Andere eingehende Beziehungen:')).toBeGreaterThan(answer.markdown.indexOf(line(answer.markdown, 'CALLS')));
|
||||
expect(line(answer.markdown, 'TESTS')).toMatch(/^- \*\*TESTS \(11\):\*\* /);
|
||||
expect(line(answer.markdown, 'DEFINES')).toBe('- **DEFINES (1):** `general.py`, die Datei, die `JSONBAgg` definiert');
|
||||
expect(answer.markdown).not.toMatch(/\bvon 1[12]\b/);
|
||||
expect(answer.markdown).not.toMatch(/\b(?:CALLS|TESTS|DEFINES) von \d/);
|
||||
const callees = relationshipAnswer('Was ruft JSONBAgg auf?', [jsonbAggEvidence()])!.markdown;
|
||||
expect(callees).toContain('Was `JSONBAgg` im geladenen Graphen aufruft. 2 ausgehende Beziehungen zu 2 Symbolen.');
|
||||
expect(callees).toContain('Weitere ausgehende Beziehungen:');
|
||||
expect(callees).toContain('`JSONBAgg` hat in diesem Ausschnitt keine ausgehende CALLS-Kante. Ausgehend: 2 Beziehungen zu 2 Symbolen.');
|
||||
expect(callees).toContain('Andere ausgehende Beziehungen:');
|
||||
expect(answer.markdown).toContain('Ausschnitt: 1 Schritt in beide Richtungen');
|
||||
});
|
||||
|
||||
@@ -118,7 +122,7 @@ describe('listed relationship answers', () => {
|
||||
|
||||
it('answers for a large documented scope with complete counts and every edge type', () => {
|
||||
const markdown = relationshipAnswer('What does postgres call?', [selectionEvidenceContext(largeFolderScope())])!.markdown;
|
||||
expect(markdown).toContain('150 outgoing relationships to 150 symbols.');
|
||||
expect(markdown).toContain('`postgres` calls 30 symbols (CALLS) in the loaded graph. All outgoing: 150 relationships to 150 symbols.');
|
||||
for (const type of ['CALLS', 'TESTS', 'USAGE', 'IMPORTS', 'DEFINES_METHOD']) expect(line(markdown, type)).toMatch(/^- \*\*\w+ \(30\):\*\* .*; \+\d+ more$/);
|
||||
expect(markdown).toContain('fully loaded.');
|
||||
});
|
||||
@@ -129,7 +133,7 @@ describe('listed relationship answers', () => {
|
||||
const markdown = relationshipAnswer('What does postgres call?', [cut])!.markdown;
|
||||
expect(markdown).not.toMatch(/to 0 symbols/);
|
||||
expect(markdown).toContain('the snapshot left part of its relationships out, so counts and names can be incomplete');
|
||||
expect(markdown).toMatch(/Outgoing: relationships left out of this snapshot\.|\d+ outgoing relationships?\./);
|
||||
expect(markdown).toMatch(/What `postgres` calls cannot be listed from this scope\. The snapshot left the outgoing relationships out\.|All outgoing: \d+ relationships? to \d+ symbols?\./);
|
||||
});
|
||||
|
||||
it('leaves questions about another symbol, attached non-Galaxy evidence and other questions to the model', () => {
|
||||
@@ -175,7 +179,7 @@ describe('tolerant caller and callee questions (K16)', () => {
|
||||
expect(relationshipQuestion(prompt)).toEqual({ sides, language, subject });
|
||||
const markdown = relationshipAnswer(prompt, [jsonbAggEvidence()])?.markdown ?? '';
|
||||
expect(markdown).toContain('`JSONBAgg`');
|
||||
expect(markdown).toContain(language === 'de' ? 'im geladenen Graphen' : 'in the loaded graph');
|
||||
expect(markdown).toContain(heading(sides[0], language));
|
||||
});
|
||||
|
||||
it.each(['falls jsonbagg fehlt, was passiert?', 'Erkläre jsonbagg', 'who calls jsonbagg and why', 'auf jsonbagg', 'cells of jsonbagg',
|
||||
@@ -197,7 +201,7 @@ describe('tolerant caller and callee questions (K16)', () => {
|
||||
expect(suggestion.markdown).toContain(language === 'de'
|
||||
? `Meintest du: ${side === 'incoming' ? 'Aufrufer von' : 'von'} \`JSONBAgg\`` : `Did you mean: ${side === 'incoming' ? 'callers of' : 'what'} \`JSONBAgg\``);
|
||||
expect(relationshipAnswer(suggestion.question, [jsonbAggEvidence()])?.markdown)
|
||||
.toContain(side === 'incoming' ? (language === 'de' ? 'Aufrufer von `JSONBAgg`' : 'Callers of `JSONBAgg`') : (language === 'de' ? 'Was `JSONBAgg` im geladenen Graphen aufruft' : 'What `JSONBAgg` calls in the loaded graph'));
|
||||
.toContain(heading(side, language));
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -271,7 +275,7 @@ describe('caller questions with a misspelled selection or a free word order (K16
|
||||
expect(question?.sides).toEqual(['incoming']);
|
||||
expect(question?.language).toBe(language);
|
||||
expect(question?.subject?.toLowerCase()).not.toMatch(/^(?:wo|woher|irgendwo|überall|where|whom)$/);
|
||||
expect(listedAnswer(prompt)).toContain(language === 'de' ? 'Aufrufer von `JSONBAgg` im geladenen Graphen' : 'Callers of `JSONBAgg` in the loaded graph');
|
||||
expect(listedAnswer(prompt)).toContain(heading('incoming', language));
|
||||
});
|
||||
|
||||
// A typo in the selected name, up to two edits and in any case: never straight to the model.
|
||||
@@ -301,7 +305,7 @@ describe('caller questions with a misspelled selection or a free word order (K16
|
||||
const listed = relationshipAnswer(prompt, evidence());
|
||||
const suggestion = relationshipSuggestion(prompt, evidence());
|
||||
if (expected === 'listed') {
|
||||
expect(listed?.markdown).toContain(language === 'de' ? 'Aufrufer von `JSONBAgg`' : 'Callers of `JSONBAgg`');
|
||||
expect(listed?.markdown).toContain(heading('incoming', language));
|
||||
return;
|
||||
}
|
||||
expect(listed).toBeUndefined();
|
||||
@@ -312,9 +316,7 @@ describe('caller questions with a misspelled selection or a free word order (K16
|
||||
// The uncertain part is the name, and the reply says so.
|
||||
if (relationshipQuestion(prompt)) expect(suggestion?.markdown).toContain(language === 'de' ? 'ist nicht genau der Name der Auswahl' : 'is not exactly the name of the selection');
|
||||
// The suggested question lists the selection when chosen.
|
||||
expect(relationshipAnswer(suggestion!.question, evidence())?.markdown).toContain(expected === 'incoming'
|
||||
? language === 'de' ? 'Aufrufer von `JSONBAgg` im geladenen Graphen' : 'Callers of `JSONBAgg` in the loaded graph'
|
||||
: language === 'de' ? 'Was `JSONBAgg` im geladenen Graphen aufruft' : 'What `JSONBAgg` calls in the loaded graph');
|
||||
expect(relationshipAnswer(suggestion!.question, evidence())?.markdown).toContain(heading(expected, language));
|
||||
});
|
||||
|
||||
it.each([
|
||||
|
||||
@@ -182,16 +182,18 @@ function listed(question: RelationshipQuestion, evidence: GalaxyEvidence): strin
|
||||
const name = quote(evidence.label);
|
||||
const sections: string[] = [];
|
||||
for (const side of question.sides) {
|
||||
const heading = side === 'incoming' ? words.callersOf(name) : words.calleesOf(name);
|
||||
if (evidence.depth === 0) { sections.push(`${heading}. ${words.notExpanded}`); continue; }
|
||||
if (!sideLoaded(evidence, side)) { sections.push(`${heading}. ${words.notLoaded(side)}`); continue; }
|
||||
const unlisted = words.unlisted(side, name);
|
||||
if (evidence.depth === 0) { sections.push(`${unlisted} ${words.notExpanded}`); continue; }
|
||||
if (!sideLoaded(evidence, side)) { sections.push(`${unlisted} ${words.notLoaded(side)}`); continue; }
|
||||
const groups = evidence.relationships[side];
|
||||
if (!groups.length) { sections.push(`${heading}. ${evidence.truncated ? words.cut(side) : words.noRelationships}`); continue; }
|
||||
if (!groups.length) { sections.push(evidence.truncated ? `${unlisted} ${words.cutListed(side)}` : words.nothing(side, name)); continue; }
|
||||
const symbols = side === 'incoming' ? evidence.relationships.incomingSymbols : evidence.relationships.outgoingSymbols;
|
||||
const total = groups.reduce((sum, group) => sum + group.count, 0);
|
||||
const calls = groups.find(group => group.type === 'CALLS');
|
||||
const others = groups.filter(group => group !== calls);
|
||||
sections.push(`${heading}. ${words.total(side, total, symbols)}${calls ? '' : ` ${words.noCalls(name, side)}`}`);
|
||||
// The heading counts the callers it lists; all relationships of the side follow apart (W3).
|
||||
sections.push(calls ? `${side === 'incoming' ? words.callers(name, calls.count) : words.callees(name, calls.count)}${others.length ? ` ${words.all(side, total, symbols)}` : ''}`
|
||||
: `${words.noCalls(name, side)} ${side === 'incoming' ? words.incoming(total, symbols) : words.outgoing(total, symbols)}`);
|
||||
if (calls) sections.push(listedLine(calls, side, words, name));
|
||||
if (others.length) sections.push(`${words.otherRelationships(side)}\n${others.map(group => listedLine(group, side, words, name)).join('\n')}`);
|
||||
}
|
||||
|
||||
@@ -74,11 +74,18 @@ const englishRelationshipWords = {
|
||||
notInScope: (label: string, kind: string) => `Selected: ${label} (${kind}); its symbols are not in the loaded scope.`,
|
||||
selectedGroup: (kind: string, label: string, count: number, listed: string, omitted: number) =>
|
||||
`Selected ${kind}: ${label} with ${en(count)} symbols: ${listed}${omitted > 0 ? `; +${en(omitted)} more` : ''}.`,
|
||||
callersOf: (name: string) => `Callers of ${name} in the loaded graph`,
|
||||
calleesOf: (name: string) => `What ${name} calls in the loaded graph`,
|
||||
/** The total of a listed answer: "23 incoming relationships from 12 symbols", never "23 from 12" (C2). */
|
||||
total: (side: 'incoming' | 'outgoing', total: number, symbols?: number) => `${en(total)} ${side} ${total === 1 ? 'relationship' : 'relationships'}`
|
||||
/** The heading of a listed answer counts what it lists, the CALLS edges; every other relationship
|
||||
* of that side is counted apart, so 23 relationships never head a list of 11 callers (W3). */
|
||||
callers: (name: string, count: number) => `${en(count)} ${count === 1 ? 'caller' : 'callers'} (CALLS) of ${name} in the loaded graph.`,
|
||||
callees: (name: string, count: number) => `${name} calls ${en(count)} ${count === 1 ? 'symbol' : 'symbols'} (CALLS) in the loaded graph.`,
|
||||
all: (side: 'incoming' | 'outgoing', total: number, symbols?: number) => `All ${side}: ${en(total)} ${total === 1 ? 'relationship' : 'relationships'}`
|
||||
+ `${symbols === undefined ? '' : ` ${side === 'incoming' ? 'from' : 'to'} ${en(symbols)} ${symbols === 1 ? 'symbol' : 'symbols'}`}.`,
|
||||
/** Why a side cannot be listed; the reason follows. */
|
||||
unlisted: (side: 'incoming' | 'outgoing', name: string) => side === 'incoming' ? `The callers of ${name} cannot be listed from this scope.`
|
||||
: `What ${name} calls cannot be listed from this scope.`,
|
||||
nothing: (side: 'incoming' | 'outgoing', name: string) => side === 'incoming' ? `${name} has no callers and no other incoming relationships in this scope.`
|
||||
: `${name} calls nothing and has no other outgoing relationships in this scope.`,
|
||||
cutListed: (side: 'incoming' | 'outgoing') => `The snapshot left the ${side} relationships out.`,
|
||||
/** One edge type of a listed answer with the number of its symbols: "TESTS (11)". */
|
||||
typeCount: (type: string, count: number) => `${type} (${en(count)})`,
|
||||
/** What an incoming DEFINES edge from a file, module or class says about the selection. */
|
||||
@@ -86,7 +93,6 @@ const englishRelationshipWords = {
|
||||
noCalls: (name: string, side: 'incoming' | 'outgoing') => side === 'incoming'
|
||||
? `No CALLS edge reaches ${name} in this scope.` : `${name} has no outgoing CALLS edge in this scope.`,
|
||||
otherRelationships: (side: 'incoming' | 'outgoing') => `Other ${side} relationships:`,
|
||||
noRelationships: 'None in this scope.',
|
||||
notLoaded: (side: 'incoming' | 'outgoing'): string => side === 'incoming'
|
||||
? 'The current scope does not follow incoming relationships. Trace incoming or both directions, then ask again.'
|
||||
: 'The current scope does not follow outgoing relationships. Trace outgoing or both directions, then ask again.',
|
||||
@@ -141,10 +147,15 @@ export const relationshipWords: { en: RelationshipWords; de: RelationshipWords }
|
||||
notInScope: (label: string, kind: string) => `Ausgewählt: ${label} (${kind}); seine Symbole sind nicht im geladenen Ausschnitt.`,
|
||||
selectedGroup: (kind: string, label: string, count: number, listed: string, omitted: number) =>
|
||||
`Ausgewählt (${kind}): ${label} mit ${de(count)} Symbolen: ${listed}${omitted > 0 ? `; +${de(omitted)} weitere` : ''}.`,
|
||||
callersOf: (name: string) => `Aufrufer von ${name} im geladenen Graphen`,
|
||||
calleesOf: (name: string) => `Was ${name} im geladenen Graphen aufruft`,
|
||||
total: (side: 'incoming' | 'outgoing', total: number, symbols?: number) => `${de(total)} ${side === 'incoming' ? 'eingehende' : 'ausgehende'} ${total === 1 ? 'Beziehung' : 'Beziehungen'}`
|
||||
+ `${symbols === undefined ? '' : ` ${side === 'incoming' ? 'aus' : 'zu'} ${de(symbols)} ${symbols === 1 ? 'Symbol' : 'Symbolen'}`}.`,
|
||||
callers: (name: string, count: number) => `${de(count)} Aufrufer (CALLS) von ${name} im geladenen Graphen.`,
|
||||
callees: (name: string, count: number) => `${name} ruft im geladenen Graphen ${de(count)} ${count === 1 ? 'Symbol' : 'Symbole'} auf (CALLS).`,
|
||||
all: (side: 'incoming' | 'outgoing', total: number, symbols?: number) => `Alle ${side === 'incoming' ? 'eingehenden' : 'ausgehenden'}: ${de(total)} ${total === 1 ? 'Beziehung' : 'Beziehungen'}`
|
||||
+ `${symbols === undefined ? '' : ` ${side === 'incoming' ? 'von' : 'zu'} ${de(symbols)} ${symbols === 1 ? 'Symbol' : 'Symbolen'}`}.`,
|
||||
unlisted: (side: 'incoming' | 'outgoing', name: string) => side === 'incoming' ? `Die Aufrufer von ${name} lassen sich aus diesem Ausschnitt nicht auflisten.`
|
||||
: `Was ${name} aufruft, lässt sich aus diesem Ausschnitt nicht auflisten.`,
|
||||
nothing: (side: 'incoming' | 'outgoing', name: string) => side === 'incoming' ? `${name} hat in diesem Ausschnitt keine Aufrufer und keine anderen eingehenden Beziehungen.`
|
||||
: `${name} ruft in diesem Ausschnitt nichts auf und hat keine anderen ausgehenden Beziehungen.`,
|
||||
cutListed: (side: 'incoming' | 'outgoing') => `Der Schnappschuss hat die ${side === 'incoming' ? 'eingehenden' : 'ausgehenden'} Beziehungen ausgelassen.`,
|
||||
typeCount: (type: string, count: number) => `${type} (${de(count)})`,
|
||||
definer: (kind: string, count: number, name: string) => {
|
||||
const noun = ({ file: ['die Datei', 'die Dateien'], module: ['das Modul', 'die Module'], class: ['die Klasse', 'die Klassen'] } as Record<string, string[]>)[kind.toLowerCase()]
|
||||
@@ -153,8 +164,8 @@ export const relationshipWords: { en: RelationshipWords; de: RelationshipWords }
|
||||
},
|
||||
noCalls: (name: string, side: 'incoming' | 'outgoing') => side === 'incoming'
|
||||
? `Keine CALLS-Kante führt in diesem Ausschnitt zu ${name}.` : `${name} hat in diesem Ausschnitt keine ausgehende CALLS-Kante.`,
|
||||
otherRelationships: (side: 'incoming' | 'outgoing') => `Weitere ${side === 'incoming' ? 'eingehende' : 'ausgehende'} Beziehungen:`,
|
||||
noRelationships: 'Keine in diesem Ausschnitt.',
|
||||
/** "Andere": the types other than CALLS, also where no CALLS edge exists (W3). */
|
||||
otherRelationships: (side: 'incoming' | 'outgoing') => `Andere ${side === 'incoming' ? 'eingehende' : 'ausgehende'} Beziehungen:`,
|
||||
notLoaded: (side: 'incoming' | 'outgoing') => side === 'incoming'
|
||||
? 'Der aktuelle Ausschnitt folgt keinen eingehenden Beziehungen. Verfolge eingehend oder beide Richtungen und frage noch einmal.'
|
||||
: 'Der aktuelle Ausschnitt folgt keinen ausgehenden Beziehungen. Verfolge ausgehend oder beide Richtungen und frage noch einmal.',
|
||||
|
||||
@@ -301,9 +301,9 @@ async function k16(page) {
|
||||
const luftCalls = await sentSince(page, luftMark);
|
||||
await shot(page, 'K16', 'luft-to-model', '"Hat diese Klasse Luft?" is not read as a call question: the model answers it.');
|
||||
const callers = ['test_default_argument', 'test_empty_result_set', 'test_jsonb_agg', 'test_values_list'];
|
||||
check('K16', 'Typo caller questions are listed; uncertain ones are suggested in the right direction and language; no model call', /Aufrufer von JSONBAgg im geladenen Graphen/.test(typo)
|
||||
&& callers.every((name) => typo.includes(name)) && /Aufrufer von JSONBAgg im geladenen Graphen/.test(shortTypo) && /Meintest du: Aufrufer von JSONBAgg\?/.test(suggestion)
|
||||
&& JSON.stringify(germanButtons) === JSON.stringify(['Liste anzeigen', 'Modell fragen']) && /Aufrufer von JSONBAgg im geladenen Graphen/.test(listed)
|
||||
check('K16', 'Typo caller questions are listed; uncertain ones are suggested in the right direction and language; no model call', /Aufrufer \(CALLS\) von JSONBAgg im geladenen Graphen/.test(typo)
|
||||
&& callers.every((name) => typo.includes(name)) && /Aufrufer \(CALLS\) von JSONBAgg im geladenen Graphen/.test(shortTypo) && /Meintest du: Aufrufer von JSONBAgg\?/.test(suggestion)
|
||||
&& JSON.stringify(germanButtons) === JSON.stringify(['Liste anzeigen', 'Modell fragen']) && /Aufrufer \(CALLS\) von JSONBAgg im geladenen Graphen/.test(listed)
|
||||
&& JSON.stringify(listedButtons) === JSON.stringify(['Modell fragen']) && /Did you mean: what JSONBAgg calls\?/.test(direction)
|
||||
&& JSON.stringify(englishButtons) === JSON.stringify(['Show the list', 'Ask the model']) && modelCalls.length === 0 && luftCalls.length === 1 && !/Meintest du|Did you mean/.test(luft),
|
||||
{ typoAnswerStart: typo.slice(0, 120), shortTypo: shortTypo.slice(0, 120), suggestion: suggestion.slice(0, 200), germanButtons, afterShowList: listed.slice(0, 120), listedButtons,
|
||||
@@ -324,10 +324,10 @@ async function k16(page) {
|
||||
await shot(page, 'K16', 'name-typo-listed', 'After "Show the list": the complete callers of JSONBAgg.');
|
||||
const typoModelCalls = (await sentSince(page, typoMark)).length;
|
||||
check('K16', 'A typo in the selected name (up to two letters, any case) is offered for the selection, a free word order with "wo" is listed; none of them reach the model',
|
||||
orders.every((item) => /Aufrufer von JSONBAgg im geladenen Graphen/.test(item.answer) && callers.every((name) => item.answer.includes(name)))
|
||||
orders.every((item) => /Aufrufer \(CALLS\) von JSONBAgg im geladenen Graphen/.test(item.answer) && callers.every((name) => item.answer.includes(name)))
|
||||
&& typos.every((item) => item.language === 'de' ? /Meintest du: Aufrufer von JSONBAgg\?/.test(item.answer) && /ist nicht genau der Name der Auswahl/.test(item.answer)
|
||||
: /Did you mean: callers of JSONBAgg\?/.test(item.answer) && /is not exactly the name of the selection/.test(item.answer))
|
||||
&& /Callers of JSONBAgg in the loaded graph/.test(typoListed) && typoModelCalls === 0,
|
||||
&& /callers \(CALLS\) of JSONBAgg in the loaded graph/.test(typoListed) && typoModelCalls === 0,
|
||||
{ orders: orders.map((item) => `${item.question} => ${item.answer.replace(/\s+/g, ' ').slice(0, 140)}`), typos: typos.map((item) => `${item.question} => ${item.answer.replace(/\s+/g, ' ').slice(0, 160)}`),
|
||||
afterShowList: typoListed.replace(/\s+/g, ' ').slice(0, 140), modelCalls: typoModelCalls });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user