Skip to content

Commit 36af1c3

Browse files
Feat/jinja2 (#13)
* feat:jinja2
1 parent ab7e955 commit 36af1c3

File tree

11 files changed

+1422
-4
lines changed

11 files changed

+1422
-4
lines changed

entity/prompt.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type TemplateType string
2525

2626
const (
2727
TemplateTypeNormal TemplateType = "normal"
28+
TemplateTypeJinja2 TemplateType = "jinja2"
2829
)
2930

3031
type Message struct {
@@ -57,8 +58,17 @@ type VariableDef struct {
5758
type VariableType string
5859

5960
const (
60-
VariableTypeString VariableType = "string"
61-
VariableTypePlaceholder VariableType = "placeholder"
61+
VariableTypeString VariableType = "string"
62+
VariableTypePlaceholder VariableType = "placeholder"
63+
VariableTypeBoolean VariableType = "boolean"
64+
VariableTypeInteger VariableType = "integer"
65+
VariableTypeFloat VariableType = "float"
66+
VariableTypeObject VariableType = "object"
67+
VariableTypeArrayString VariableType = "array<string>"
68+
VariableTypeArrayBoolean VariableType = "array<boolean>"
69+
VariableTypeArrayInteger VariableType = "array<integer>"
70+
VariableTypeArrayFloat VariableType = "array<float>"
71+
VariableTypeArrayObject VariableType = "array<object>"
6272
)
6373

6474
type ToolChoiceType string
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
2+
// SPDX-License-Identifier: MIT
3+
4+
package main
5+
6+
import (
7+
"context"
8+
"encoding/json"
9+
"fmt"
10+
"net/http"
11+
"time"
12+
13+
"github.com/coze-dev/cozeloop-go"
14+
"github.com/coze-dev/cozeloop-go/entity"
15+
"github.com/coze-dev/cozeloop-go/internal/util"
16+
"github.com/coze-dev/cozeloop-go/spec/tracespec"
17+
)
18+
19+
// If you want to use the jinja templates in prompts, you can refer to the following.
20+
func main() {
21+
// 1.Create a prompt on the platform
22+
// You can create a Prompt on the platform's Prompt development page (set Prompt Key to 'prompt_hub_demo'), add the following messages to the template, and submit a version.
23+
// System: You are a helpful bot, the conversation topic is {{var1}}.
24+
// Placeholder: placeholder1
25+
// User: My question is {{var2}}
26+
// Placeholder: placeholder2
27+
28+
ctx := context.Background()
29+
30+
// Set the following environment variables first.
31+
// COZELOOP_WORKSPACE_ID=your workspace id
32+
// COZELOOP_API_TOKEN=your token
33+
// 2.New loop client
34+
client, err := cozeloop.NewClient(
35+
// Set whether to report a trace span when get or format prompt.
36+
// Default value is false.
37+
cozeloop.WithPromptTrace(true))
38+
if err != nil {
39+
panic(err)
40+
}
41+
42+
llmRunner := llmRunner{
43+
client: client,
44+
}
45+
46+
// 1. start root span
47+
ctx, span := llmRunner.client.StartSpan(ctx, "root_span", "main_span", nil)
48+
49+
// 3.Get the prompt
50+
prompt, err := llmRunner.client.GetPrompt(ctx, cozeloop.GetPromptParam{
51+
PromptKey: "prompt_hub_demo",
52+
// If version is not specified, the latest version of the corresponding prompt will be obtained
53+
Version: "0.0.1",
54+
})
55+
if err != nil {
56+
fmt.Printf("get prompt failed: %v\n", err)
57+
return
58+
}
59+
if prompt != nil {
60+
// Get messages of the prompt
61+
if prompt.PromptTemplate != nil {
62+
messages, err := json.Marshal(prompt.PromptTemplate.Messages)
63+
if err != nil {
64+
fmt.Printf("json marshal failed: %v\n", err)
65+
return
66+
}
67+
fmt.Printf("prompt messages=%s\n", string(messages))
68+
}
69+
// Get llm config of the prompt
70+
if prompt.LLMConfig != nil {
71+
llmConfig, err := json.Marshal(prompt.LLMConfig)
72+
if err != nil {
73+
fmt.Printf("json marshal failed: %v\n", err)
74+
}
75+
fmt.Printf("prompt llm config=%s\n", llmConfig)
76+
}
77+
78+
// 4.Format messages of the prompt
79+
userMessageContent := "Hello!"
80+
assistantMessageContent := "Hello!"
81+
82+
messages, err := llmRunner.client.PromptFormat(ctx, prompt, map[string]any{
83+
"var_string": "hi",
84+
"var_int": 5,
85+
"var_bool": true,
86+
"var_float": 1.0,
87+
"var_object": map[string]interface{}{
88+
"name": "John",
89+
"age": 30,
90+
"hobbies": []string{"reading", "coding"},
91+
"address": map[string]interface{}{
92+
"city": "bejing",
93+
"street": "123 Main",
94+
},
95+
},
96+
"var_array_string": []string{
97+
"hello", "nihao",
98+
},
99+
"var_array_boolean": []bool{
100+
true, false, true,
101+
},
102+
"var_array_int": []int64{
103+
1, 2, 3, 4,
104+
},
105+
"var_array_float": []float64{
106+
1.0, 2.0,
107+
},
108+
"var_array_object": []interface{}{
109+
map[string]interface{}{"key": "123"},
110+
map[string]interface{}{"value": 100},
111+
},
112+
// Placeholder variable type should be entity.Message/*entity.Message/[]entity.Message/[]*entity.Message
113+
"placeholder1": []*entity.Message{
114+
{
115+
Role: entity.RoleUser,
116+
Content: &userMessageContent,
117+
},
118+
{
119+
Role: entity.RoleAssistant,
120+
Content: &assistantMessageContent,
121+
},
122+
},
123+
// Other variables in the prompt template that are not provided with corresponding values will be considered as empty values
124+
})
125+
if err != nil {
126+
fmt.Printf("prompt format failed: %v\n", err)
127+
return
128+
}
129+
data, err := json.Marshal(messages)
130+
if err != nil {
131+
fmt.Printf("json marshal failed: %v\n", err)
132+
return
133+
}
134+
fmt.Printf("formatted messages=%s\n", string(data))
135+
136+
// 5. llm call
137+
err = llmRunner.llmCall(ctx, messages)
138+
if err != nil {
139+
return
140+
}
141+
}
142+
143+
// 6. span finish
144+
span.Finish(ctx)
145+
146+
// 7. (optional) flush or close
147+
// -- force flush, report all traces in the queue
148+
// Warning! In general, this method is not needed to be call, as spans will be automatically reported in batches.
149+
// Note that flush will block and wait for the report to complete, and it may cause frequent reporting,
150+
// affecting performance.
151+
llmRunner.client.Flush(ctx)
152+
}
153+
154+
type llmRunner struct {
155+
client cozeloop.Client
156+
}
157+
158+
func (r *llmRunner) llmCall(ctx context.Context, messages []*entity.Message) (err error) {
159+
ctx, span := r.client.StartSpan(ctx, "llmCall", tracespec.VModelSpanType, nil)
160+
defer span.Finish(ctx)
161+
162+
// llm is processing
163+
//baseURL := "https://xxx"
164+
//ak := "****"
165+
modelName := "gpt-4o-2024-05-13"
166+
maxTokens := 1000 // range: [0, 4096]
167+
//transport := &MyTransport{
168+
// DefaultTransport: &http.Transport{},
169+
//}
170+
//config := openai.DefaultAzureConfig(ak, baseURL)
171+
//config.HTTPClient = &http.Client{
172+
// Transport: transport,
173+
//}
174+
//client := openai.NewClientWithConfig(config)
175+
//marshal, err := json.Marshal(messages)
176+
//if err != nil {
177+
// return err
178+
//}
179+
//chatCompletionMessage := make([]openai.ChatCompletionMessage, 0)
180+
//err = json.Unmarshal(marshal, &chatCompletionMessage)
181+
//if err != nil {
182+
// return err
183+
//}
184+
//resp, err := client.CreateChatCompletion(
185+
// ctx,
186+
// openai.ChatCompletionRequest{
187+
// Model: modelName,
188+
// Messages: chatCompletionMessage,
189+
// MaxTokens: maxTokens,
190+
// TopP: 0.95,
191+
// N: 1,
192+
// PresencePenalty: 1.0,
193+
// FrequencyPenalty: 1.0,
194+
// Temperature: 0.6,
195+
// },
196+
//)
197+
198+
// mock resp
199+
time.Sleep(1 * time.Second)
200+
respChoices := []string{
201+
"Hello! Can I help you?",
202+
}
203+
respPromptTokens := 11
204+
respCompletionTokens := 52
205+
206+
// set tag key: `input`
207+
span.SetInput(ctx, convertModelInput(messages))
208+
// set tag key: `output`
209+
span.SetOutput(ctx, respChoices)
210+
// set tag key: `model_provider`, e.g., openai, etc.
211+
span.SetModelProvider(ctx, "openai")
212+
// set tag key: `start_time_first_resp`
213+
// Timestamp of the first packet return from LLM, unit: microseconds.
214+
// When `start_time_first_resp` is set, a tag named `latency_first_resp` calculated
215+
// based on the span's StartTime will be added, meaning the latency for the first packet.
216+
span.SetStartTimeFirstResp(ctx, time.Now().UnixMicro())
217+
// set tag key: `input_tokens`. The amount of input tokens.
218+
// when the `input_tokens` value is set, it will automatically sum with the `output_tokens` to calculate the `tokens` tag.
219+
span.SetInputTokens(ctx, respPromptTokens)
220+
// set tag key: `output_tokens`. The amount of output tokens.
221+
// when the `output_tokens` value is set, it will automatically sum with the `input_tokens` to calculate the `tokens` tag.
222+
span.SetOutputTokens(ctx, respCompletionTokens)
223+
// set tag key: `model_name`, e.g., gpt-4-1106-preview, etc.
224+
span.SetModelName(ctx, modelName)
225+
span.SetTags(ctx, map[string]interface{}{
226+
tracespec.CallOptions: tracespec.ModelCallOption{
227+
Temperature: 0.6,
228+
MaxTokens: int64(maxTokens),
229+
TopP: 0.95,
230+
N: 1,
231+
PresencePenalty: util.Ptr(float32(1.0)),
232+
FrequencyPenalty: util.Ptr(float32(1.0)),
233+
},
234+
})
235+
236+
return nil
237+
}
238+
239+
type MyTransport struct {
240+
Header http.Header
241+
DefaultTransport http.RoundTripper
242+
}
243+
244+
func (transport *MyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
245+
for key, values := range transport.Header {
246+
for _, value := range values {
247+
req.Header.Add(key, value)
248+
}
249+
}
250+
return transport.DefaultTransport.RoundTrip(req)
251+
}
252+
253+
func convertModelInput(messages []*entity.Message) *tracespec.ModelInput {
254+
modelMessages := make([]*tracespec.ModelMessage, 0)
255+
for _, message := range messages {
256+
modelMessages = append(modelMessages, &tracespec.ModelMessage{
257+
Role: string(message.Role),
258+
Content: util.PtrValue(message.Content),
259+
})
260+
}
261+
262+
return &tracespec.ModelInput{
263+
Messages: modelMessages,
264+
}
265+
}

go.mod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,27 @@ require (
77
github.com/bytedance/mockey v1.2.14
88
github.com/coze-dev/cozeloop-go/spec v0.1.0
99
github.com/golang-jwt/jwt v3.2.2+incompatible
10+
github.com/nikolalohinski/gonja/v2 v2.3.1
1011
github.com/smartystreets/goconvey v1.8.1
1112
github.com/valyala/fasttemplate v1.2.2
1213
golang.org/x/sync v0.11.0
1314
)
1415

1516
require (
17+
github.com/dustin/go-humanize v1.0.1 // indirect
1618
github.com/gopherjs/gopherjs v1.17.2 // indirect
19+
github.com/json-iterator/go v1.1.12 // indirect
1720
github.com/jtolds/gls v4.20.0+incompatible // indirect
21+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
22+
github.com/modern-go/reflect2 v1.0.2 // indirect
23+
github.com/pkg/errors v0.9.1 // indirect
24+
github.com/sirupsen/logrus v1.9.3 // indirect
1825
github.com/smarty/assertions v1.15.0 // indirect
1926
github.com/valyala/bytebufferpool v1.0.0 // indirect
2027
golang.org/x/arch v0.11.0 // indirect
28+
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect
2129
golang.org/x/sys v0.26.0 // indirect
30+
golang.org/x/text v0.14.0 // indirect
2231
)
2332

2433
replace github.com/coze-dev/cozeloop-go/spec => ./spec

go.sum

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,66 @@
1+
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
12
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
23
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
34
github.com/bytedance/mockey v1.2.14 h1:KZaFgPdiUwW+jOWFieo3Lr7INM1P+6adO3hxZhDswY8=
45
github.com/bytedance/mockey v1.2.14/go.mod h1:1BPHF9sol5R1ud/+0VEHGQq/+i2lN+GTsr3O2Q9IENY=
6+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
8+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9+
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
10+
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
11+
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
12+
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
513
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
614
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
15+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
16+
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
17+
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
718
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
819
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
20+
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
21+
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
922
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
1023
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
24+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
25+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
26+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
27+
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
28+
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
29+
github.com/nikolalohinski/gonja/v2 v2.3.1 h1:UGyLa6NDNq6dCGkFY33sziUssjTdh95xrYslxZdqNVU=
30+
github.com/nikolalohinski/gonja/v2 v2.3.1/go.mod h1:1Wcc/5huTu6y36e0sOFR1XQoFlylw3c3H3L5WOz0RDg=
31+
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
32+
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
33+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
34+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
35+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
36+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
37+
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
38+
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
1139
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
1240
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
1341
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
1442
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
43+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
44+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
45+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
46+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
1547
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
1648
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
1749
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
1850
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
1951
golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4=
2052
golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
53+
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8=
54+
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
55+
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
2156
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
2257
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
58+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2359
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
2460
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
61+
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
62+
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
63+
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
64+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
65+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
66+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

internal/consts/error.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var (
1616
ErrAuthInfoRequired = NewError("api token or jwt oauth info is required")
1717
ErrParsePrivateKey = NewError("failed to parse private key")
1818
ErrHeaderParent = NewError("header traceparent is illegal")
19+
ErrTemplateRender = NewError("template render error")
1920
)
2021

2122
type LoopError struct {

0 commit comments

Comments
 (0)