Support inherited PromptKit profiles

This commit is contained in:
2026-08-25 19:31:00 +00:00
parent 2be999ebd3
commit 75a3f51cee
7 changed files with 136 additions and 3 deletions

View File

@@ -456,6 +456,32 @@ func TestPromptKitClientCheckpointFingerprintTracksProfileSource(t *testing.T) {
t.Fatalf("profile-source fingerprint exposes source path: %#v, %#v", first, second)
}
})
t.Run("inherited parent", func(t *testing.T) {
profileDir := t.TempDir()
parentPath := filepath.Join(profileDir, "parent.yaml")
leafPath := filepath.Join(profileDir, "leaf.yaml")
if err := os.WriteFile(parentPath, []byte("id: parent\nendpoint: http://promptkit.test/v1\nmodel: parent-one\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(leafPath, []byte("id: leaf\nbase_profile: parent\nmodel: leaf-model\n"), 0o600); err != nil {
t.Fatal(err)
}
first, err := promptKitProfileFingerprint(profileDir, "", "")
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(parentPath, []byte("id: parent\nendpoint: http://promptkit.test/v1\nmodel: parent-two\n"), 0o600); err != nil {
t.Fatal(err)
}
second, err := promptKitProfileFingerprint(profileDir, "", "")
if err != nil {
t.Fatal(err)
}
if first == second || strings.Contains(first.Value, "parent-one") || strings.Contains(first.Value, parentPath) || strings.Contains(first.Value, leafPath) {
t.Fatalf("inherited profile fingerprint = %#v then %#v", first, second)
}
})
}
func TestPromptKitProfileFingerprintReadErrorsDoNotExposeSourcePaths(t *testing.T) {
@@ -531,6 +557,78 @@ func TestPromptKitClientUsesFallbackProfilesForExecutionAndInspection(t *testing
}
}
func TestPromptKitClientUsesInheritedFilesystemProfileForInspectionAndExecution(t *testing.T) {
profileDir := t.TempDir()
if err := os.WriteFile(filepath.Join(profileDir, "base.yaml"), []byte("id: base\nendpoint: http://promptkit.test/v1\nmodel: base-model\nreasoning_effort: medium\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(profileDir, "leaf.yaml"), []byte("id: inherited-profile\nbase_profile: base\nmodel: leaf-model\n"), 0o600); err != nil {
t.Fatal(err)
}
fake := &fakePromptKitLLM{content: `{"ok":true}`}
client, err := NewPromptKitClient(PromptKitClientConfig{Assets: newTestPromptKitAssets(t), ProfileDir: profileDir, EngineOptions: []promptkit.Option{promptkit.WithLLMClient(fake)}})
if err != nil {
t.Fatal(err)
}
inspector, err := NewPromptKitProfileInspector(PromptKitProfileInspectorConfig{Source: PromptKitProfileSourceConfig{ProfileDir: profileDir}})
if err != nil {
t.Fatal(err)
}
inspection, err := inspector.InspectProfile(context.Background(), "inherited-profile")
if err != nil {
t.Fatal(err)
}
if inspection.ProfileID != "inherited-profile" || inspection.Model != "leaf-model" {
t.Fatalf("inspection = %#v, want resolved leaf target", inspection)
}
var out map[string]any
response, err := client.CompleteStructured(context.Background(), contracts.StructuredCompletionRequest{PromptID: "adapter.test", ProfileID: "inherited-profile", SessionID: "inheritance-test", Inputs: contracts.LLMInputSet{"transcript": contracts.NewLLMInputMaterial("transcript", "application/json", []byte(`{"source":true}`), "", "")}}, &out)
if err != nil {
t.Fatal(err)
}
if response.ProfileID != inspection.ProfileID || response.Model != inspection.Model || fake.lastRequest().Target.ReasoningEffort != "medium" {
t.Fatalf("response=%#v target=%#v inspection=%#v", response, fake.lastRequest().Target, inspection)
}
}
func TestPromptKitProfileInspectorExposesRakestrawhomeBuiltIn(t *testing.T) {
inspector, err := NewPromptKitProfileInspector(PromptKitProfileInspectorConfig{})
if err != nil {
t.Fatal(err)
}
inspection, err := inspector.InspectProfile(context.Background(), "rakestrawhome-gemma-4-31b")
if err != nil {
t.Fatal(err)
}
if inspection.BackendID != promptkit.BackendRakestrawHome || inspection.Model != "google/gemma-4-31b-it" {
t.Fatalf("inspection = %#v", inspection)
}
}
func TestPromptKitClientAllowsMissingOptionalFilesystemCredential(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if got := r.Header.Get("Authorization"); got != "" {
t.Fatalf("Authorization = %q, want omitted", got)
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"choices":[{"message":{"content":"{\"ok\":true}"}}]}`))
}))
defer server.Close()
t.Setenv("NOTARIUS_OPTIONAL_PROFILE_KEY", "")
profilePath := filepath.Join(t.TempDir(), "optional.yaml")
if err := os.WriteFile(profilePath, []byte("id: optional-profile\nendpoint: "+server.URL+"/v1\nmodel: optional-model\napi_key_env: NOTARIUS_OPTIONAL_PROFILE_KEY\n"), 0o600); err != nil {
t.Fatal(err)
}
client, err := NewPromptKitClient(PromptKitClientConfig{Assets: newTestPromptKitAssets(t), ProfileFile: profilePath})
if err != nil {
t.Fatal(err)
}
var out map[string]any
if _, err := client.CompleteStructured(context.Background(), contracts.StructuredCompletionRequest{PromptID: "adapter.test", ProfileID: "optional-profile", SessionID: "optional-credential-test", Inputs: contracts.LLMInputSet{"transcript": contracts.NewLLMInputMaterial("transcript", "application/json", []byte(`{"source":true}`), "", "")}}, &out); err != nil {
t.Fatal(err)
}
}
func TestPromptKitClientCheckpointFingerprintTracksFallbackProfileAssets(t *testing.T) {
fingerprintFor := func(content string) CheckpointFingerprint {
t.Helper()