code.oscarkilo.com/klex-git

Hash:
098e5bd263e946425d591c6f137b6565947fa06d
Author:
Igor Naverniouk <[email protected]>
Date:
Tue Jun 2 18:37:00 2026 -0400
Message:
api: add Klex interface and Fake test double Introduce api.Klex covering the AI-ops surface of the client (F, Messages, Embed), and api.Fake — a configurable in-process implementation that lets downstream tests stub responses without spinning up httptest servers or hand-rolling per-project mocks. Motivation: //lab/memory needs to unit-test its fact-extraction pipeline end-to-end through the Klex client. Putting the test double here means every project that uses Klex can standardize on one mock rather than each repo inventing its own shape. Usage: fake := &api.Fake{ FFunc: func(name, in string) (string, error) { return "canned response", nil }, } var k api.Klex = fake *Client satisfies Klex via its existing methods, so production code that switches a *Client field to api.Klex continues to work unchanged. Three tests cover the happy path, the unset-handler error, and an error returned from a handler. Does not touch api/api.go; the in-progress MessagesStream edits there are left for a separate commit.
diff --git a/api/fake.go b/api/fake.go
new file mode 100644
index 0000000..7dfb371
--- /dev/null
+++ b/api/fake.go
@@ -0,0 +1,42 @@
+package api
+
+import "fmt"
+
+// Fake is a configurable test double for Klex. Set the handler fields
+// for the methods the test exercises; unset methods return an error.
+//
+// Example:
+//
+// var k Klex = &Fake{
+// FFunc: func(name, in string) (string, error) {
+// return "canned response", nil
+// },
+// }
+type Fake struct {
+ FFunc func(name, in string) (string, error)
+ MessagesFunc func(req MessagesRequest) (*MessagesResponse, error)
+ EmbedFunc func(req EmbedRequest) ([][]float32, error)
+}
+
+func (f *Fake) F(name, in string) (string, error) {
+ if f.FFunc == nil {
+ return "", fmt.Errorf("Fake.F: no handler set")
+ }
+ return f.FFunc(name, in)
+}
+
+func (f *Fake) Messages(
+ req MessagesRequest,
+) (*MessagesResponse, error) {
+ if f.MessagesFunc == nil {
+ return nil, fmt.Errorf("Fake.Messages: no handler set")
+ }
+ return f.MessagesFunc(req)
+}
+
+func (f *Fake) Embed(req EmbedRequest) ([][]float32, error) {
+ if f.EmbedFunc == nil {
+ return nil, fmt.Errorf("Fake.Embed: no handler set")
+ }
+ return f.EmbedFunc(req)
+}
diff --git a/api/fake_test.go b/api/fake_test.go
new file mode 100644
index 0000000..77f4fe4
--- /dev/null
+++ b/api/fake_test.go
@@ -0,0 +1,55 @@
+package api
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+func TestFakeF(t *testing.T) {
+ var capturedName, capturedIn string
+ f := &Fake{
+ FFunc: func(name, in string) (string, error) {
+ capturedName, capturedIn = name, in
+ return "echo: " + in, nil
+ },
+ }
+
+ out, err := f.F("greet", "world")
+ if err != nil {
+ t.Fatalf("F: %v", err)
+ }
+ if out != "echo: world" {
+ t.Errorf("Out: got %q, want %q", out, "echo: world")
+ }
+ if capturedName != "greet" || capturedIn != "world" {
+ t.Errorf("captured: name=%q in=%q",
+ capturedName, capturedIn)
+ }
+}
+
+func TestFakeFUnset(t *testing.T) {
+ f := &Fake{}
+ _, err := f.F("any", "any")
+ if err == nil {
+ t.Fatal("expected error, got nil")
+ }
+ if !strings.Contains(err.Error(), "no handler") {
+ t.Errorf("error: %v", err)
+ }
+}
+
+func TestFakeMessagesError(t *testing.T) {
+ f := &Fake{
+ MessagesFunc: func(
+ req MessagesRequest,
+ ) (*MessagesResponse, error) {
+ return nil, fmt.Errorf("synthetic")
+ },
+ }
+ _, err := f.Messages(MessagesRequest{Model: "test"})
+ if err == nil {
+ t.Fatal("expected error, got nil")
+ }
+}
+
diff --git a/api/klex.go b/api/klex.go
new file mode 100644
index 0000000..778a180
--- /dev/null
+++ b/api/klex.go
@@ -0,0 +1,12 @@
+package api
+
+// Klex is the Klex client interface. The real implementation is
+// *Client (api.go); tests can substitute *Fake (fake.go).
+//
+// The interface covers the AI-ops surface of the Klex API. It starts
+// minimal and grows as consumers need more methods.
+type Klex interface {
+ F(name, in string) (string, error)
+ Messages(req MessagesRequest) (*MessagesResponse, error)
+ Embed(req EmbedRequest) ([][]float32, error)
+}
/dev/null
b/api/fake.go
1
package api
2
3
import "fmt"
4
5
// Fake is a configurable test double for Klex. Set the handler fields
6
// for the methods the test exercises; unset methods return an error.
7
//
8
// Example:
9
//
10
// var k Klex = &Fake{
11
// FFunc: func(name, in string) (string, error) {
12
// return "canned response", nil
13
// },
14
// }
15
type Fake struct {
16
FFunc func(name, in string) (string, error)
17
MessagesFunc func(req MessagesRequest) (*MessagesResponse, error)
18
EmbedFunc func(req EmbedRequest) ([][]float32, error)
19
}
20
21
func (f *Fake) F(name, in string) (string, error) {
22
if f.FFunc == nil {
23
return "", fmt.Errorf("Fake.F: no handler set")
24
}
25
return f.FFunc(name, in)
26
}
27
28
func (f *Fake) Messages(
29
req MessagesRequest,
30
) (*MessagesResponse, error) {
31
if f.MessagesFunc == nil {
32
return nil, fmt.Errorf("Fake.Messages: no handler set")
33
}
34
return f.MessagesFunc(req)
35
}
36
37
func (f *Fake) Embed(req EmbedRequest) ([][]float32, error) {
38
if f.EmbedFunc == nil {
39
return nil, fmt.Errorf("Fake.Embed: no handler set")
40
}
41
return f.EmbedFunc(req)
42
}
/dev/null
b/api/fake_test.go
1
package api
2
3
import (
4
"fmt"
5
"strings"
6
"testing"
7
)
8
9
func TestFakeF(t *testing.T) {
10
var capturedName, capturedIn string
11
f := &Fake{
12
FFunc: func(name, in string) (string, error) {
13
capturedName, capturedIn = name, in
14
return "echo: " + in, nil
15
},
16
}
17
18
out, err := f.F("greet", "world")
19
if err != nil {
20
t.Fatalf("F: %v", err)
21
}
22
if out != "echo: world" {
23
t.Errorf("Out: got %q, want %q", out, "echo: world")
24
}
25
if capturedName != "greet" || capturedIn != "world" {
26
t.Errorf("captured: name=%q in=%q",
27
capturedName, capturedIn)
28
}
29
}
30
31
func TestFakeFUnset(t *testing.T) {
32
f := &Fake{}
33
_, err := f.F("any", "any")
34
if err == nil {
35
t.Fatal("expected error, got nil")
36
}
37
if !strings.Contains(err.Error(), "no handler") {
38
t.Errorf("error: %v", err)
39
}
40
}
41
42
func TestFakeMessagesError(t *testing.T) {
43
f := &Fake{
44
MessagesFunc: func(
45
req MessagesRequest,
46
) (*MessagesResponse, error) {
47
return nil, fmt.Errorf("synthetic")
48
},
49
}
50
_, err := f.Messages(MessagesRequest{Model: "test"})
51
if err == nil {
52
t.Fatal("expected error, got nil")
53
}
54
}
55
/dev/null
b/api/klex.go
1
package api
2
3
// Klex is the Klex client interface. The real implementation is
4
// *Client (api.go); tests can substitute *Fake (fake.go).
5
//
6
// The interface covers the AI-ops surface of the Klex API. It starts
7
// minimal and grows as consumers need more methods.
8
type Klex interface {
9
F(name, in string) (string, error)
10
Messages(req MessagesRequest) (*MessagesResponse, error)
11
Embed(req EmbedRequest) ([][]float32, error)
12
}