fillContextualAI function exported

Last updated: 2026-03-04T23:21:38.398Z

Metrics

LOC: 129 Complexity: 22 Params: 2

Signature

fillContextualAI( context?: AIContextPayload, ): : Promise<GenerationResult[]>

Summary

Fills all form fields on the page using Chrome AI contextual generation. All values are generated in a single AI call, producing a cohesive fictional identity (same person/company across every field). Falls back to {@link fillAllFields} if AI is unavailable or returns no data.

Architecture violations

View all

  • [warning] max-cyclomatic-complexity: 'fillContextualAI' has cyclomatic complexity 22 (max 10)
  • [warning] max-lines: 'fillContextualAI' has 129 lines (max 80)

Tags

#@param context - Optional user-provided context (text, CSV, audio, image) to guide AI#@returns Array of generation results for each filled field

Source Code

export async function fillContextualAI(
  context?: AIContextPayload,
): Promise<GenerationResult[]> {
  setFillingInProgress(true);
  const progress = createProgressNotification();
  progress.show();
  try {
    const { fields } = await detectAllFieldsAsync();
    if (fields.length === 0) {
      progress.destroy();
      return [];
    }

    const url = window.location.href;
    const settings = await getSettings();
    const ignoredFields = await getIgnoredFieldsForUrl(url);
    const ignoredSelectors = new Set(ignoredFields.map((f) => f.selector));

    const eligibleFields = fields.filter(
      (f) => !ignoredSelectors.has(f.selector),
    );

    const fillableFields = settings.fillEmptyOnly
      ? eligibleFields.filter((f) => !fieldHasValue(f))
      : eligibleFields;

    if (fillableFields.length === 0) {
      progress.destroy();
      return [];
    }

    // Build compact descriptors for the AI
    const contextInputs: FormContextFieldInput[] = fillableFields.map(
      (f, i) => {
        const input: FormContextFieldInput = {
          index: i,
          label: f.label ?? f.name ?? f.id ?? undefined,
          fieldType: f.fieldType,
          inputType:
            f.element instanceof HTMLInputElement
              ? f.element.type || "text"
              : undefined,
        };

        if (f.element instanceof HTMLSelectElement) {
          const opts = Array.from(f.element.options)
            .filter((o) => o.value.trim().length > 0)
            .map((o) => o.text.trim() || o.value)
            .slice(0, 6);
          if (opts.length > 0) return { ...input, options: opts };
        }

        return input;
      },
    );

    // Show spinner while the single batch AI call is in-flight
    progress.showAiGenerating();

    const contextMap = await generateFormContextValuesViaProxy(
      contextInputs,
      buildUserContextString(context),
      context?.imageDataUrl,
      context?.pdfPageDataUrls,
    );

    progress.hideAiGenerating();

    if (!contextMap || Object.keys(contextMap).length === 0) {
      log.warn(
        "fillContextualAI: AI não retornou valores, usando fallback fillAllFields",
      );
      progress.destroy();
      return fillAllFields();
    }

    const results: GenerationResult[] = [];

    for (let i = 0; i < fillableFields.length; i++) {
      const field = fillableFields[i]!;
      const value = contextMap[String(i)];

      if (!value) continue;

      progress.addFilling(field);

      try {
        await applyValueToField(field, value);

        logAuditFill({
          selector: field.selector,
          fieldType: field.fieldType,
          source: "ai",
          value,
        });

        if (settings.highlightFilled) {
          highlightField(
            field.element,
            field.label ?? field.fieldType ?? undefined,
          );
        }

        if (settings.showAiBadge) {
          showAiFieldBadge(field.element);
        }

        const result: GenerationResult = {
          fieldSelector: field.selector,
          value,
          source: "ai",
        };
        progress.updateFilled(field, result);
        results.push(result);
      } catch (err) {
        log.warn(`fillContextualAI: falhou no campo ${field.selector}:`, err);
        progress.updateError(
          field,
          err instanceof Error ? err.message : "falhou",
        );
      }
    }

    progress.done(results.length, fillableFields.length);
    return results;
  } finally {
    setFillingInProgress(false);
  }
}

Dependencies (Outgoing)

graph LR fillContextualAI["fillContextualAI"] setFillingInProgress["setFillingInProgress"] createProgressNotification["createProgressNotification"] detectAllFieldsAsync["detectAllFieldsAsync"] fieldHasValue["fieldHasValue"] buildUserContextString["buildUserContextString"] fillAllFields["fillAllFields"] applyValueToField["applyValueToField"] highlightField["highlightField"] showAiFieldBadge["showAiFieldBadge"] fillContextualAI -->|calls| setFillingInProgress fillContextualAI -->|calls| createProgressNotification fillContextualAI -->|calls| detectAllFieldsAsync fillContextualAI -->|calls| fieldHasValue fillContextualAI -->|calls| buildUserContextString fillContextualAI -->|calls| fillAllFields fillContextualAI -->|calls| applyValueToField fillContextualAI -->|calls| highlightField fillContextualAI -->|calls| showAiFieldBadge style fillContextualAI fill:#dbeafe,stroke:#2563eb,stroke-width:2px click fillContextualAI "854e1a4562eb49e4.html" click setFillingInProgress "5404cb0266e02c7f.html" click createProgressNotification "2f3f7f6d24a2f425.html" click detectAllFieldsAsync "1b422b3353cdbe22.html" click fieldHasValue "5a7659a4d189d652.html" click buildUserContextString "c7237ee5672c23a4.html" click fillAllFields "12dbe3fb8e692059.html" click applyValueToField "59a962012828c5cb.html" click highlightField "d079b946779ebfc9.html" click showAiFieldBadge "91a8abe473f9bccf.html"

Impact (Incoming)

graph LR fillContextualAI["fillContextualAI"] FillableElement["FillableElement"] toggleWatch["toggleWatch"] makeInput["makeInput"] FillableElement -->|uses| fillContextualAI toggleWatch -->|uses| fillContextualAI makeInput -->|uses| fillContextualAI style fillContextualAI fill:#dbeafe,stroke:#2563eb,stroke-width:2px click fillContextualAI "854e1a4562eb49e4.html" click FillableElement "2ecf5aaac3f668a8.html" click toggleWatch "5b1d47a07d7aa0c9.html" click makeInput "3b463c3c3297bb7c.html"
SourceType
FillableElement uses
toggleWatch uses
makeInput uses