repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

3.6 KB · 111 lines · Go Raw History
  1package skills
  2
  3import (
  4	"context"
  5	"strings"
  6	"testing"
  7)
  8
  9func TestURLsIn(t *testing.T) {
 10	cases := []struct {
 11		q    string
 12		want []string
 13	}{
 14		{"summary of this https://cloudinabottle.org/blog/launch-post",
 15			[]string{"https://cloudinabottle.org/blog/launch-post"}},
 16		{"what does https://example.com/a say, and is it right?",
 17			[]string{"https://example.com/a"}},
 18		{"read (https://example.com/a) and http://example.org/b",
 19			[]string{"https://example.com/a", "http://example.org/b"}},
 20		{"the same one twice https://example.com/a https://example.com/a",
 21			[]string{"https://example.com/a"}},
 22		{"how many people live in http land", nil},
 23		{"what is https://localhost about", nil},
 24		{"a query string survives https://example.com/a?b=c&d=e#f",
 25			[]string{"https://example.com/a?b=c&d=e#f"}},
 26		{"summarise https://en.wikipedia.org/wiki/Go_(programming_language)",
 27			[]string{"https://en.wikipedia.org/wiki/Go_(programming_language)"}},
 28		{"summarise (https://en.wikipedia.org/wiki/Go_(programming_language)).",
 29			[]string{"https://en.wikipedia.org/wiki/Go_(programming_language)"}},
 30	}
 31	for _, c := range cases {
 32		got := URLsIn(c.q)
 33		if strings.Join(got, "|") != strings.Join(c.want, "|") {
 34			t.Errorf("%q: got %v, want %v", c.q, got, c.want)
 35		}
 36	}
 37}
 38
 39// The claim is the whole routing decision for this one, so it has to hold
 40// without a model. Decide is handed a nil model on purpose: reaching for it
 41// would panic, which is the assertion.
 42func TestPageClaimsWithoutTheModel(t *testing.T) {
 43	r := Default()
 44	route := r.Decide(context.Background(), nil, "summary of this https://cloudinabottle.org/blog/launch-post")
 45	if route.Skill != "page" {
 46		t.Fatalf("got %s, want page (%s)", route.Skill, route.Why())
 47	}
 48	if got := r.match("tl;dr https://example.com/post"); got != "page" {
 49		t.Errorf("offline matcher got %s, want page", got)
 50	}
 51}
 52
 53// A claiming skill is kept out of the prompt the model reads, since it can
 54// never be the answer to a question with no address in it.
 55func TestPageIsNotInTheRoutingPrompt(t *testing.T) {
 56	r := Default()
 57	if strings.Contains(r.systemPrompt(), "page:") {
 58		t.Error("the page card is in the routing prompt, which is noise on every other question")
 59	}
 60	for _, n := range r.routable() {
 61		if n == "page" {
 62			t.Error("page is in the enum the model chooses from")
 63		}
 64	}
 65}
 66
 67func TestPageRun(t *testing.T) {
 68	res, err := (Page{}).Run(context.Background(), "summary of this https://example.com/post", Deps{})
 69	if err != nil {
 70		t.Fatal(err)
 71	}
 72	if res == nil || len(res.URLs) != 1 || res.URLs[0] != "https://example.com/post" {
 73		t.Fatalf("got %+v", res)
 74	}
 75	if res.Text != "" {
 76		t.Error("it gathers rather than answers, so it must not write text")
 77	}
 78	if res.Shape != "summary" {
 79		t.Errorf("shape is %q, want summary", res.Shape)
 80	}
 81
 82	// The router can only send it a question with an address in it, but a
 83	// skill that trusts the router has no way of declining.
 84	if res, _ := (Page{}).Run(context.Background(), "what is a summary", Deps{}); res != nil {
 85		t.Error("claimed a question with no address in it")
 86	}
 87}
 88
 89func TestWantsProbability(t *testing.T) {
 90	for _, q := range []string{
 91		"what are the odds on the us open",
 92		"who is favoured to win the election",
 93		"chances of a rate cut this month",
 94		"is trump going to win",
 95	} {
 96		if !wantsProbability(q) {
 97			t.Errorf("%q should read as a question about how likely something is", q)
 98		}
 99	}
100	for _, q := range []string{
101		"how is the us open going",
102		"what's the score in the us open",
103		"who won the us open",
104		"when is the election",
105	} {
106		if wantsProbability(q) {
107			t.Errorf("%q is not asking for a price", q)
108		}
109	}
110}