harn-cli 0.5.83

CLI for the Harn programming language — run, test, REPL, format, and lint
import { fireEvent, render, screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { IntlProvider } from "react-intl"
import { describe, expect, it, vi } from "vitest"

import { LaunchPanel } from "./LaunchPanel"

describe("LaunchPanel", () => {
  it("submits playground launches with provider, model, and env overrides", async () => {
    const onLaunch = vi.fn(async () => {})

    render(
      <IntlProvider locale="en">
        <LaunchPanel
          meta={{ workspace_root: "/workspace/harn", run_dir: ".harn-runs/portal-demo" }}
          llmOptions={{
            preferred_provider: "openai",
            preferred_model: "gpt-4.1-mini",
            providers: [
              {
                name: "openai",
                base_url: "https://api.openai.com/v1",
                base_url_env: null,
                auth_style: "bearer",
                auth_envs: ["OPENAI_API_KEY"],
                auth_configured: true,
                viable: true,
                local: false,
                models: ["gpt-4.1-mini"],
                aliases: [],
                default_model: "gpt-4.1-mini",
              },
            ],
          }}
          targets={[{ path: "examples/demo.harn", group: "examples" }]}
          jobs={[]}
          onLaunch={onLaunch}
          onOpenRun={() => {}}
        />
      </IntlProvider>,
    )

    await userEvent.clear(screen.getByLabelText("Task"))
    await userEvent.type(screen.getByLabelText("Task"), "Draft a release note")
    fireEvent.change(screen.getByLabelText("Env JSON overrides"), {
      target: { value: '{"OPENAI_API_KEY":"test-key"}' },
    })
    await userEvent.click(screen.getAllByRole("button", { name: "Run now" }).at(-1)!)

    expect(onLaunch).toHaveBeenCalledWith({
      env: { OPENAI_API_KEY: "test-key" },
      file_path: undefined,
      model: "gpt-4.1-mini",
      provider: "openai",
      source: undefined,
      task: "Draft a release note",
    })
  })

  it("renders launch workspace details and open-run actions", async () => {
    const onOpenRun = vi.fn()

    render(
      <IntlProvider locale="en">
        <LaunchPanel
          meta={{ workspace_root: "/workspace/harn", run_dir: ".harn-runs/portal-demo" }}
          llmOptions={{
            preferred_provider: "openai",
            preferred_model: "gpt-4.1-mini",
            providers: [
              {
                name: "openai",
                base_url: "https://api.openai.com/v1",
                base_url_env: null,
                auth_style: "bearer",
                auth_envs: ["OPENAI_API_KEY"],
                auth_configured: true,
                viable: true,
                local: false,
                models: ["gpt-4.1-mini"],
                aliases: [],
                default_model: "gpt-4.1-mini",
              },
            ],
          }}
          targets={[]}
          jobs={[
            {
              id: "job-1",
              mode: "playground",
              target_label: "playground: debug prompt",
              status: "completed",
              started_at: "started-1",
              finished_at: "finished-1",
              exit_code: 0,
              logs: "completed",
              discovered_run_paths: ["playground/job-1/run.json"],
              workspace_dir: "/tmp/harn/job-1",
              transcript_path: "/tmp/harn/job-1/run-llm/llm_transcript.jsonl",
            },
          ]}
          onLaunch={async () => {}}
          onOpenRun={onOpenRun}
        />
      </IntlProvider>,
    )

    expect(screen.getByText("/tmp/harn/job-1")).toBeInTheDocument()
    expect(screen.getByText("/tmp/harn/job-1/run-llm/llm_transcript.jsonl")).toBeInTheDocument()

    await userEvent.click(screen.getByRole("button", { name: "Open run playground/job-1/run.json" }))
    expect(onOpenRun).toHaveBeenCalledWith("playground/job-1/run.json")
  })

  it("allows custom model input and endpoint overrides for local providers", async () => {
    const onLaunch = vi.fn(async () => {})

    render(
      <IntlProvider locale="en">
        <LaunchPanel
          meta={{ workspace_root: "/workspace/harn", run_dir: ".harn-runs/portal-demo" }}
          llmOptions={{
            preferred_provider: "local",
            preferred_model: "gpt-4o",
            providers: [
              {
                name: "local",
                base_url: "http://localhost:8000",
                base_url_env: "LOCAL_LLM_BASE_URL",
                auth_style: "none",
                auth_envs: [],
                auth_configured: true,
                viable: true,
                local: true,
                models: ["gpt-4o"],
                aliases: [],
                default_model: "gpt-4o",
              },
            ],
          }}
          targets={[]}
          jobs={[]}
          onLaunch={onLaunch}
          onOpenRun={() => {}}
        />
      </IntlProvider>,
    )

    await userEvent.selectOptions(screen.getAllByLabelText("Model").at(-1)!, "Custom…")
    fireEvent.change(screen.getByLabelText("Custom model"), {
      target: { value: "qwen2.5-coder:latest" },
    })
    fireEvent.change(screen.getAllByLabelText(/Endpoint URL/).at(-1)!, {
      target: { value: "http://192.168.1.40:8000" },
    })
    await userEvent.click(screen.getAllByRole("button", { name: "Run now" }).at(-1)!)

    expect(onLaunch).toHaveBeenCalledWith({
      env: { LOCAL_LLM_BASE_URL: "http://192.168.1.40:8000" },
      file_path: undefined,
      model: "qwen2.5-coder:latest",
      provider: "local",
      source: undefined,
      task: "Summarize the repository in a few bullets.",
    })
  })
})