generateFormContextValues function exported ✗ 0.0%

Last updated: 2026-03-03T18:32:34.140Z

Metrics

LOC: 133 Complexity: 18 Params: 4 Coverage: 0.0% (0/48 lines, 0x executed)

Signature

generateFormContextValues( fields: readonly FormContextFieldInput[], userContext?: string, imageBlobs?: Blob[], ): : Promise<FormContextOutput | null>

Summary

Generates coherent values for ALL form fields at once using a single Chrome AI call. All values belong to the same fictional person/entity.

Architecture violations

View all

  • [warning] max-cyclomatic-complexity: 'generateFormContextValues' has cyclomatic complexity 18 (max 10)
  • [warning] max-lines: 'generateFormContextValues' has 133 lines (max 80)

Tags

#@param fields - Array of compact field descriptors (index, label, type, options)#@param userContext - Optional freeform context string to guide generation#@param imageBlobs - Optional image blobs (uploaded image + rendered PDF pages)#@returns A map of `"index" → "value"` or `null` when AI is unavailable/fails

Source Code

export async function generateFormContextValues(
  fields: readonly FormContextFieldInput[],
  userContext?: string,
  imageBlobs?: Blob[],
): Promise<FormContextOutput | null> {
  if (fields.length === 0) return null;

  const batch = fields.slice(0, FORM_CONTEXT_MAX_FIELDS);
  log.debug(
    `Gerando contexto para ${batch.length} campos com Chrome AI... (imagens: ${imageBlobs?.length ?? 0})`,
  );

  const aiSession = await getSession();
  if (!aiSession) {
    log.warn("Sessão Chrome AI indisponível — contexto não gerado.");
    return null;
  }

  const hasImages = imageBlobs !== undefined && imageBlobs.length > 0;

  // When images are present, prepend a strict extraction instruction so the
  // model reads values from the document instead of hallucinating them.
  const imageInstruction = hasImages
    ? "IMPORTANT: One or more document images are attached. Extract field values DIRECTLY from the images. " +
      "Do NOT invent or guess values that are not visible in the images. " +
      "Only use the generator rules for fields whose values are NOT present in the images.\n"
    : undefined;

  const textPrompt = formContextGeneratorPrompt.buildPrompt(
    batch,
    imageInstruction
      ? [imageInstruction, userContext].filter(Boolean).join("\n")
      : userContext,
  );

  // When images are present, a separate session must be created with
  // expectedInputs: [{ type: "image" }] — the shared global session does not
  // support images.
  let promptSession: LanguageModelSession | null = aiSession;
  let tempSession: LanguageModelSession | null = null;
  if (hasImages) {
    const api = getLanguageModelApi();
    if (api) {
      try {
        log.debug("Criando sessão com suporte a imagens...");
        tempSession = await api.create({
          systemPrompt: renderSystemPrompt(fieldValueGeneratorPrompt),
          expectedInputs: [
            { type: "text", languages: ["en"] },
            { type: "image" },
          ],
          expectedOutputs: [{ type: "text", languages: ["en"] }],
          // Low temperature + topK=1: model must extract from the image,
          // not hallucinate. When visual context is present, creativity
          // is a bug, not a feature.
          temperature: 0.2,
          topK: 1,
        });
        promptSession = tempSession;
        log.debug("Sessão com imagens criada.");
      } catch (err) {
        log.warn(
          "Sessão com suporte a imagens indisponível — usando apenas texto:",
          err,
        );
        // Fall back to text-only
      }
    }
  }

  // Build multimodal input.
  // Chrome AI requires role-based messages when content includes images.
  const promptInput: LanguageModelPromptInput =
    hasImages && tempSession
      ? [
          {
            role: "user" as const,
            content: [
              { type: "text" as const, value: textPrompt },
              ...imageBlobs!.map(
                (blob): LanguageModelImagePart => ({
                  type: "image",
                  value: blob,
                }),
              ),
            ],
          },
        ]
      : textPrompt;

  log.groupCollapsed("Prompt → form-context-generator");
  log.debug("▶ Prompt:\n" + textPrompt);
  if (hasImages)
    log.debug(
      `▶ Imagens (${imageBlobs!.length}): ` +
        imageBlobs!.map((b) => `${b.type} (${b.size}b)`).join(", "),
    );
  log.groupEnd();

  let raw: string;
  try {
    raw = await promptSession!.prompt(promptInput);
  } catch (err) {
    log.warn("Erro ao gerar contexto de formulário — destruindo sessão:", err);
    if (tempSession) {
      tempSession.destroy();
    } else {
      session?.destroy();
      session = null;
    }
    return null;
  } finally {
    // Always destroy the temporary image session after use
    if (tempSession) {
      tempSession.destroy();
    }
  }

  log.groupCollapsed("Resposta ← form-context-generator");
  log.debug("◄ Resposta raw:\n" + raw);
  log.groupEnd();

  const result = formContextGeneratorPrompt.parseResponse(raw);
  if (!result) {
    log.warn("Falha ao parsear JSON da resposta contextual. Raw:\n" + raw);
    return null;
  }

  log.info(
    `Contexto gerado com sucesso: ${Object.keys(result).length} campos.`,
  );
  return result;
}

Dependencies (Outgoing)

graph LR generateFormContextValues["generateFormContextValues"] getSession["getSession"] getLanguageModelApi["getLanguageModelApi"] generateFormContextValues -->|calls| getSession generateFormContextValues -->|calls| getLanguageModelApi style generateFormContextValues fill:#dbeafe,stroke:#2563eb,stroke-width:2px click generateFormContextValues "599bada0365a8514.html" click getSession "59bdb203dfc665ba.html" click getLanguageModelApi "410ff2233e0b1dc2.html"
TargetType
getSession calls
getLanguageModelApi calls

Impact (Incoming)

graph LR generateFormContextValues["generateFormContextValues"] getLanguageModelApi["getLanguageModelApi"] getLanguageModelApi -->|uses| generateFormContextValues style generateFormContextValues fill:#dbeafe,stroke:#2563eb,stroke-width:2px click generateFormContextValues "599bada0365a8514.html" click getLanguageModelApi "64fb30d22107f96b.html"
SourceType
getLanguageModelApi uses