Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,26 @@ The syntax-highlighting definitions in internal/tui/render/lexers are generated
from the lexers of Chroma (https://github.com/alecthomas/chroma), Copyright (C)
2017 Alec Thomas, used under the MIT license. See internal/tui/render/lexers for
that license text and for how the files are regenerated.

The chat templates in internal/inference/launch/templates are copied unchanged
from their publishers and used under the Apache License, Version 2.0:
gpt-oss.jinja is the gpt-oss chat template published by OpenAI at
https://huggingface.co/openai/gpt-oss-20b; gemma4.jinja is the Gemma 4 chat
template published by Google at https://huggingface.co/google/gemma-4-12B-it.
The revision of each is recorded in internal/inference/launch/template.go.

Gemma 4 is licensed by Google under Apache 2.0 (the model card declares
license: apache-2.0 and links https://ai.google.dev/gemma/docs/gemma_4_license,
which is the unmodified Apache 2.0 text). Unlike earlier Gemma releases, it is
not under the Gemma Terms of Use (https://ai.google.dev/gemma/terms), whose
scope lists only those earlier models and which points Gemma 4 to its own
licence. The template and the weights are under the same terms; Flynn does not
distribute the weights.

The container security profiles in deploy/seccomp/flynn.json and
deploy/apparmor/flynn-container are Docker's default seccomp profile and
AppArmor template from moby/profiles (https://github.com/moby/profiles),
Copyright The Moby Authors, used under the Apache License, Version 2.0. Each
is modified by one rule, described in dev/container-profiles, which also
pins the upstream commit. Unchanged copies of the upstream files are in
deploy/testdata.
8 changes: 5 additions & 3 deletions internal/inference/launch/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ import (
// from the model.

// gptOSSTemplate is OpenAI's published chat template for gpt-oss (the chat_template.jinja
// in openai/gpt-oss-20b, Apache-2.0), byte for byte the template the ggml-org GGUF
// in openai/gpt-oss-20b at revision 6cee5e81ee83917806bbde320786a8fb61efebee,
// Apache-2.0, attributed in NOTICE), byte for byte the template the ggml-org GGUF
// conversion embeds. It renders the harmony format, including tool definitions and the
// reasoning_effort setting.
//
//go:embed templates/gpt-oss.jinja
var gptOSSTemplate string

// gemma4Template is Google's canonical Gemma 4 chat template (Apache-2.0), as embedded in
// google/gemma-4-12B-it-qat-q4_0-gguf. llama.cpp has no built-in name for Gemma 4; it
// gemma4Template is Google's canonical Gemma 4 chat template (the chat_template.jinja in
// google/gemma-4-12B-it at revision 43c9d014b231474fa7212dbb48a762566c2b255d, Apache-2.0,
// attributed in NOTICE), byte for byte. llama.cpp has no built-in name for Gemma 4; it
// recognises the family from the template source, so the source has to be supplied.
//
//go:embed templates/gemma4.jinja
Expand Down
22 changes: 22 additions & 0 deletions internal/inference/launch/template_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package launch

import (
"crypto/sha256"
"encoding/hex"
"strings"
"testing"
)
Expand Down Expand Up @@ -174,3 +176,23 @@ func TestNativeToolCallsFollowsTheRoute(t *testing.T) {
t.Error("llama3 runs with --no-jinja and cannot take tools")
}
}

// TestEmbeddedTemplatesAreThePublishersOwn holds each embedded template to the SHA-256 of
// the file its publisher ships at the revision recorded on its variable. NOTICE states the
// templates are copied unchanged, and an edit made here would break that statement and
// leave Flynn serving a prompt format no upstream model was trained on. Updating a template
// means taking the publisher's newer file whole, then updating the revision and this digest.
func TestEmbeddedTemplatesAreThePublishersOwn(t *testing.T) {
for name, want := range map[string]string{
"gpt-oss": "a4c9919cbbd4acdd51ccffe22da049264b1b73e59055fa58811a99efbd7c8146",
"gemma4": "ae53464bf3be25802b3a5b37def7fd89667067d7577049b3b2d74c4d8de4c6d4",
} {
sum := sha256.Sum256([]byte(embeddedTemplates[name]))
if got := hex.EncodeToString(sum[:]); got != want {
t.Errorf("%s template sha256 = %s, want the publisher's %s", name, got, want)
}
}
if len(embeddedTemplates) != 2 {
t.Errorf("embedded templates = %d, want 2: a new one needs its publisher's digest here and a NOTICE entry", len(embeddedTemplates))
}
}
9 changes: 5 additions & 4 deletions watch/marker.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Package watch turns in-tree source comments into governed run inputs. It tails a
// working tree for aider-style ai! and ai? markers left in trailing comments; when
// one appears it becomes a turn the agent runs, and the marker's file and line are
// carried onto the run so its provenance lands in the sealed record like any other
// input. The marker is cleared once picked up so the same request never fires twice.
// working tree for trailing comments that open with an ai! marker (change the code) or
// an ai? marker (answer a question); when one appears it becomes a turn the agent runs,
// and the marker's file and line are carried onto the run so its provenance lands in the
// sealed record like any other input. The marker is cleared once picked up so the same
// request never fires twice.
package watch

import (
Expand Down
Loading