Back to Body Journal
SOURCE / PINNED RELEASE

Made of little things.

Body Journal

Release
e8049f8da4e2…
Author-recorded commit
61c04bf0e8aa…
License
LICENSE
Author’s source reference
nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-6c4554844c7

Archive hash verified: 4369d778da046a8b…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

src/inference-adapter.ts
import { cvm, storage } from "@napplet/sdk";
import type { CvmServerRef, JsonObject } from "@napplet/sdk";
import { parseReport, REPORT_INSTRUCTIONS, object } from "./ai-contract.js";
import { IMAGE_CHUNK_CHARS, type BodyImage } from "./vision-contract.js";

type Part =
  | { type: "text"; text: string }
  | { type: "image"; mimeType: string; data: string };
export type Model = {
  handle: string;
  name: string;
  model: string;
  route: string;
  images: boolean;
  json: boolean;
};
export type Llm = {
  select(requirements: { json?: boolean; images?: boolean }): Promise<Model>;
  describe(handle: string): Promise<Model>;
  generate(
    request: {
      handle: string;
      format: "text" | "json";
      messages: { role: "system" | "user"; content: Part[] }[];
    },
    options: { signal: AbortSignal },
  ): Promise<{ content: unknown[]; finish: string }>;
};
/** Optional experiment adapter: host injects the draft binding; this app never sends wire messages. */
export function llm(): Llm | undefined {
  return (window as unknown as { napplet?: { llm?: Llm } }).napplet?.llm;
}
export function validateAnalysis(
  raw: unknown,
  caseText: string,
  photoCount: number,
) {
  const report = parseReport(raw, true),
    ids = JSON.parse(caseText).concerns.map((c: { id: number }) => c.id);
  if (
    report.assessments!.length !== ids.length ||
    report.assessments!.some((a) => !ids.includes(a.concernId)) ||
    new Set(report.assessments!.map((a) => a.concernId)).size !== ids.length
  )
    throw new Error("The report omitted or invented an observation.");
  if (photoCount === 0 && report.evidence!.visual.length)
    throw new Error(
      "The report contains photo findings although no patient photos were shared.",
    );
  return report;
}
export async function shellReport(
  model: Model,
  caseText: string,
  images: BodyImage[],
  signal: AbortSignal,
) {
  const api = llm();
  if (!api)
    throw new Error(
      "This shell does not offer the draft NAP-LLM interface. Use the paid service or another supporting shell.",
    );
  const content: Part[] = [{ type: "text", text: caseText }];
  for (const image of images) {
    const match = /^data:(image\/(?:png|jpeg|webp));base64,(.+)$/.exec(
      image.dataUrl,
    );
    if (!match) throw new Error("Invalid prepared image.");
    content.push(
      { type: "text", text: `${image.kind || "body-map"}: ${image.caption}` },
      { type: "image", mimeType: match[1], data: match[2] },
    );
  }
  const result = await api.generate(
    {
      handle: model.handle,
      // JSON transport is an optimization, not a requirement for a text report.
      // The same strict report validation runs for both provider modes below.
      format: model.json ? "json" : "text",
      messages: [
        {
          role: "system",
          content: [{ type: "text", text: REPORT_INSTRUCTIONS }],
        },
        { role: "user", content },
      ],
    },
    { signal },
  );
  if (result.finish !== "stop")
    throw new Error(
      `The model did not finish the report (${result.finish}). No partial assessment was accepted.`,
    );
  // Thinking is display-only; this consumer does not request or execute tools.
  // Accept only completed text blocks as the report, never a partial delta.
  if (!Array.isArray(result.content))
    throw new Error("The shell returned an unsupported report format.");
  let text = "";
  for (const raw of result.content) {
    const part = object(raw);
    if (part.type === "thinking" && typeof part.text === "string") continue;
    if (part.type !== "text" || typeof part.text !== "string")
      throw new Error("The report contains an unexpected content block. No assessment was accepted.");
    text += part.text;
  }
  signal.throwIfAborted();
  return {
    report: validateAnalysis(
      JSON.parse(text),
      caseText,
      images.filter((i) => i.kind === "patient-photo").length,
    ),
    model: model.model,
  };
}
export type PaidOrder = {
  receipt: string;
  ref: CvmServerRef;
  caseText: string;
  imageCount: number;
  photoCount: number;
  invoice?: string;
  amountMsat?: number;
  orderId?: string;
  status?: string;
  model?: string;
  expectedMsat?: number;
  paymentConfirmation?: "manual" | "automatic";
  expiresAt?: number;
  paymentProtocol?: "cep8";
  paymentReceived?: boolean;
};
export const ORDER_KEY = "body-journal:paid-order:v1";
export async function rememberOrder(order: PaidOrder) {
  await storage.setItem(ORDER_KEY, JSON.stringify(order));
}
const wait = (signal: AbortSignal) =>
  new Promise<void>((resolve, reject) => {
    const stop = () => {
      clearTimeout(timer);
      reject(
        new Error("Stopped waiting. Your paid order remains recoverable."),
      );
    };
    const timer = setTimeout(() => {
      signal.removeEventListener("abort", stop);
      resolve();
    }, 2500);
    signal.addEventListener("abort", stop, { once: true });
    if (signal.aborted) stop();
  });
export class PaidClient {
  async call(
    ref: CvmServerRef,
    tool: string,
    args: Record<string, unknown>,
    timeoutMs = 20000,
    payment: "deny" | "prompt" = "deny",
  ) {
    const response = await cvm.callTool(ref, tool, args as JsonObject, {
      timeoutMs,
      initialize: true,
      payment,
    });
    if (response.isError)
      throw new Error(
        "The CVM tool failed. No native payment gate was authorized.",
      );
    const body = object(
      response.structuredContent ??
        JSON.parse(
          response.content?.find((c) => c.type === "text")?.text ?? "{}",
        ),
    );
    if (body.ok !== true)
      throw new Error(
        typeof body.message === "string"
          ? body.message
          : "The paid service could not complete this operation.",
      );
    return body;
  }
  private validate(order: PaidOrder, state: Record<string, unknown>) {
    if (
      !Number.isSafeInteger(state.amountMsat) ||
      state.amountMsat !== order.expectedMsat ||
      typeof state.orderId !== "string" ||
      !/^[a-f0-9]{64}$/.test(state.orderId) ||
      (order.orderId !== undefined && state.orderId !== order.orderId) ||
      ![
        "prepared",
        "creating",
        "awaiting-payment",
        "generating",
        "complete",
        "attention",
      ].includes(String(state.status))
    )
      throw new Error(
        "The service returned an unexpected order or amount. Keep your receipt; do not pay.",
      );
    if (
      state.status === "awaiting-payment" &&
      state.paymentProtocol !== "cep8" &&
      (typeof state.invoice !== "string" ||
        !/^lnbc/i.test(state.invoice) ||
        state.invoice.length > 12000)
    )
      throw new Error("Invalid report invoice.");
  }
  private async saveState(order: PaidOrder, state: Record<string, unknown>) {
    this.validate(order, state);
    Object.assign(order, {
      invoice: state.invoice,
      amountMsat: state.amountMsat,
      orderId: state.orderId,
      status: state.status,
      paymentConfirmation:
        state.paymentConfirmation === "manual" ? "manual" : "automatic",
      paymentProtocol: state.paymentProtocol === "cep8" ? "cep8" : undefined,
      paymentReceived: state.paymentReceived === true,
      expiresAt:
        typeof state.expiresAt === "number" ? state.expiresAt : undefined,
    });
    await rememberOrder(order);
  }
  async confirm(order: PaidOrder) {
    // Only the explicit checkout action calls this. Status/recovery stay passive.
    const state = await this.call(
      order.ref,
      "body_journal_paid_confirm",
      { receipt: order.receipt },
      45000,
    );
    await this.saveState(order, state);
    return state;
  }
  info(ref: CvmServerRef) {
    return this.call(ref, "body_journal_paid_info", {});
  }
  async prepare(order: PaidOrder, images: BodyImage[], signal: AbortSignal) {
    order.status = "staging";
    await rememberOrder(order); // no invoice exists until a durable receipt is retained
    const refs = [];
    for (const image of images) {
      const sha256 = Array.from(
        new Uint8Array(
          await crypto.subtle.digest(
            "SHA-256",
            new TextEncoder().encode(image.dataUrl),
          ),
        ),
        (b) => b.toString(16).padStart(2, "0"),
      ).join("");
      const id = "image-" + crypto.randomUUID(),
        total = Math.ceil(image.dataUrl.length / IMAGE_CHUNK_CHARS);
      for (let index = 0; index < total; index++) {
        signal.throwIfAborted();
        await this.call(order.ref, "body_journal_paid_image", {
          id,
          sha256,
          index,
          total,
          chunk: image.dataUrl.slice(
            index * IMAGE_CHUNK_CHARS,
            (index + 1) * IMAGE_CHUNK_CHARS,
          ),
        });
      }
      refs.push({
        id,
        sha256,
        concernId: image.concernId,
        kind: image.kind || "body-map",
        caption: image.caption.slice(0, 1200),
        ...(image.attachmentId ? { attachmentId: image.attachmentId } : {}),
      });
    }
    signal.throwIfAborted();
    order.status = "creating";
    await rememberOrder(order);
    const result = await this.call(order.ref, "body_journal_paid_prepare", {
      receipt: order.receipt,
      caseText: order.caseText,
      images: refs,
    });
    await this.saveState(order, result);
    return result;
  }
  close(order: PaidOrder) {
    return cvm.close(order.ref);
  }
  async run(order: PaidOrder) {
    const state = await this.call(
      order.ref,
      "body_journal_paid_run",
      { receipt: order.receipt },
      300000,
      "prompt",
    );
    await this.saveState(order, state);
    return state;
  }
  async status(order: PaidOrder) {
    const state = await this.call(order.ref, "body_journal_paid_status", {
      receipt: order.receipt,
    });
    await this.saveState(order, state);
    return state;
  }
  async poll(
    order: PaidOrder,
    signal: AbortSignal,
    update: (state: Record<string, unknown>) => void,
  ) {
    for (;;) {
      signal.throwIfAborted();
      const state = await this.call(order.ref, "body_journal_paid_status", {
        receipt: order.receipt,
      });
      signal.throwIfAborted();
      await this.saveState(order, state);
      update(state);
      if (state.status === "complete") return object(state.result);
      if (
        state.paymentProtocol === "cep8" &&
        ["prepared", "awaiting-payment"].includes(String(state.status))
      )
        return null;
      if (state.status === "attention" || state.status === "creating")
        throw new Error(
          String(
            state.message ||
              "This order needs operator attention. Keep its recovery receipt; do not pay again.",
          ),
        );
      await wait(signal);
    }
  }
}