LCOV - code coverage report
Current view: top level - dashql-app/src/agent - script_references.ts Coverage Total Hit
Test: DashQL 6e74948 Lines: 100.0 % 29 29
Test Date: 2026-11-06 17:46:50

            Line data    Source code
       1              : /// The character that starts a script reference in natural language, e.g. ":revenue".
       2              : /// It follows the named parameters of Hyper, ":name".
       3              : export const SCRIPT_REFERENCE_PREFIX = ':';
       4              : 
       5              : /// A character that continues a script name, a reference must not be followed by one
       6            1 : const NAME_CHAR = /[\p{L}\p{N}_$-]/u;
       7              : 
       8              : /// A reference to a session script in natural language text
       9              : export interface ScriptReference {
      10              :     /// The begin of the reference, at the prefix
      11              :     from: number;
      12              :     /// The end of the reference
      13              :     to: number;
      14              :     /// The display name of the referenced script
      15              :     name: string;
      16              : }
      17              : 
      18              : /// Render the reference of a script
      19            1 : export function renderScriptReference(name: string): string {
      20            1 :     return `${SCRIPT_REFERENCE_PREFIX}${name}`;
      21            1 : }
      22              : 
      23              : /// Find the references to session scripts in a text.
      24              : /// A reference is the prefix followed by the display name of a script, the longest name wins.
      25              : /// Names compare case-insensitively, the prefix must not be part of a word ("12:30", "http://") or a cast ("x::text").
      26            1 : export function findScriptReferences(names: readonly string[], text: string): ScriptReference[] {
      27            1 :     const references: ScriptReference[] = [];
      28            1 :     if (names.length === 0) {
      29            1 :         return references;
      30              :     }
      31            1 :     const lowerText = text.toLowerCase();
      32            1 :     const candidates = names
      33            1 :         .map(name => ({ name, lower: name.toLowerCase() }))
      34            1 :         .sort((l, r) => r.lower.length - l.lower.length);
      35            1 :     for (let at = text.indexOf(SCRIPT_REFERENCE_PREFIX); at >= 0; at = text.indexOf(SCRIPT_REFERENCE_PREFIX, at + 1)) {
      36            1 :         if (at > 0 && (NAME_CHAR.test(text[at - 1]) || text[at - 1] === SCRIPT_REFERENCE_PREFIX)) {
      37            1 :             continue;
      38              :         }
      39            1 :         const begin = at + SCRIPT_REFERENCE_PREFIX.length;
      40            1 :         const match = candidates.find(candidate => candidate.lower.length > 0
      41            1 :             && lowerText.startsWith(candidate.lower, begin)
      42            1 :             && !NAME_CHAR.test(text[begin + candidate.lower.length] ?? ''));
      43            1 :         if (match == null) {
      44            1 :             continue;
      45              :         }
      46            1 :         references.push({ from: at, to: begin + match.lower.length, name: match.name });
      47            1 :         at = begin + match.lower.length - 1;
      48            1 :     }
      49            1 :     return references;
      50            1 : }
      51              : 
      52              : /// The distinct names of the scripts that a text references, in the order of their first reference
      53            1 : export function collectReferencedScripts(names: readonly string[], text: string): string[] {
      54            1 :     return [...new Set(findScriptReferences(names, text).map(reference => reference.name))];
      55            1 : }
        

Generated by: LCOV version 2.0-1