Skip to content
Open
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
2 changes: 1 addition & 1 deletion backend/cmd/ctester/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import (
func main() {
envFile := flag.String("env", ".env", "Path to environment file")
providerType := flag.String("type", "custom", "Provider type [custom, openai, anthropic, gemini, bedrock, ollama, deepseek, glm, kimi, qwen, minimax, mistral, xai]")
providerName := flag.String("name", "", "Provider name using as PROVDER_NAME/MODEL_NAME while building provider config")
providerName := flag.String("name", "", "Provider name using as PROVIDER_NAME/MODEL_NAME while building provider config")
configPath := flag.String("config", "", "Path to provider config file")
testsPath := flag.String("tests", "", "Path to custom tests YAML file")
reportPath := flag.String("report", "", "Path to write report file")
Expand Down
6 changes: 3 additions & 3 deletions backend/cmd/ftester/worker/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ func (t *tester) Execute(args []string) error {
}

// If flowID > 0 and the function requires terminal preparation, prepare it
if t.flowID > 0 && t.needsTeminalPrepare(funcName) {
if t.flowID > 0 && t.needsTerminalPrepare(funcName) {
terminal.PrintInfo("Preparing container for terminal operations...")
if err := t.flowExecutor.Prepare(t.ctx); err != nil {
return fmt.Errorf("failed to prepare executor: %w", err)
Expand Down Expand Up @@ -666,8 +666,8 @@ func (t *tester) showFunctionHelp(funcName string) error {
return nil
}

// needsTeminalPrepare determines if a function needs terminal preparation
func (t *tester) needsTeminalPrepare(funcName string) bool {
// needsTerminalPrepare determines if a function needs terminal preparation
func (t *tester) needsTerminalPrepare(funcName string) bool {
// These functions require terminal preparation
terminalFunctions := map[string]bool{
tools.TerminalToolName: true,
Expand Down
68 changes: 34 additions & 34 deletions backend/docs/llms_how_to.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ cleanedChain := ast.Messages()
**What stays preserved**:
- All text content
- Tool call IDs (after normalization)
- Function names and arguments
- Function names and arguments
- Tool responses

**Automatic handling**: Both `NormalizeToolCallIDs()` and `ClearReasoning()` are called automatically in `restoreChain()` to ensure full compatibility when switching providers.
Expand Down Expand Up @@ -254,13 +254,13 @@ graph LR
B --> C[Message 1]
C --> D[Message 2]
D --> E[Message 3]

style A fill:#90EE90
style B fill:#90EE90
style C fill:#90EE90
style D fill:#FFD700
style E fill:#FFD700

A -.invalidates.-> B
B -.invalidates.-> C
```
Expand Down Expand Up @@ -910,7 +910,7 @@ This is required for tools to work correctly.
```

**Automatic Protection**: The summarization algorithm (`chain_summary.go`) automatically:
1. **Skips the last body pair** in `summarizeOversizedBodyPairs()`
1. **Skips the last body pair** in `summarizeOversizedBodyPairs()`
2. **Always preserves the most recent interaction** in `determineLastSectionPairs()`
3. **Maintains reasoning signatures** for continued conversation

Expand Down Expand Up @@ -1125,7 +1125,7 @@ msgs := []llms.MessageContent{
}},
}
resp1, _ := llm.GenerateContent(ctx, msgs, llms.WithModel("gpt-4.1-mini"))
// CacheWrite: > 0, CachRead: 0
// CacheWrite: > 0, CacheRead: 0

// Turn 2 - Simple text part works!
msgs = append(msgs,
Expand Down Expand Up @@ -1343,7 +1343,7 @@ When building applications that switch between providers, be aware of these **CR
// ✓ UNIVERSAL - Works for all providers
func buildAIMessage(choice *llms.ContentChoice) llms.MessageContent {
var parts []llms.ContentPart

// Preserve reasoning if present (required for Anthropic/Gemini, harmless for OpenAI)
if choice.Reasoning != nil {
parts = append(parts,
Expand All @@ -1352,10 +1352,10 @@ func buildAIMessage(choice *llms.ContentChoice) llms.MessageContent {
} else {
parts = append(parts, llms.TextPart(choice.Content))
}

// Add tool calls
parts = append(parts, choice.ToolCalls...)

return llms.MessageContent{
Role: llms.ChatMessageTypeAI,
Parts: parts,
Expand All @@ -1380,17 +1380,17 @@ func buildAIMessage(choice *llms.ContentChoice) llms.MessageContent {
```go
func extractReasoning(resp *llms.ContentResponse, provider string) *reasoning.ContentReasoning {
choice := resp.Choices[0]

switch provider {
case "anthropic", "openai":
return choice.Reasoning // Always at choice level

case "gemini":
if len(choice.ToolCalls) > 0 {
return choice.ToolCalls[0].Reasoning // First tool for tool calls
}
return choice.Reasoning // Choice level for text

default:
// Universal fallback: check both locations
if choice.Reasoning != nil {
Expand Down Expand Up @@ -1428,7 +1428,7 @@ func buildReasoningOptions(provider string, wantedTemp float64) []llms.CallOptio
opts := []llms.CallOption{
llms.WithReasoning(llms.ReasoningMedium, 2048),
}

switch provider {
case "anthropic":
opts = append(opts, llms.WithTemperature(1.0)) // Force 1.0
Expand All @@ -1438,7 +1438,7 @@ func buildReasoningOptions(provider string, wantedTemp float64) []llms.CallOptio
case "gemini":
opts = append(opts, llms.WithTemperature(wantedTemp)) // Flexible
}

return opts
}
```
Expand All @@ -1460,7 +1460,7 @@ func buildReasoningOptions(provider string, wantedTemp float64) []llms.CallOptio
```go
func setupCaching(provider string, systemPrompt string) []llms.CallOption {
var opts []llms.CallOption

switch provider {
case "anthropic":
// Inline cache control with strategy
Expand All @@ -1473,7 +1473,7 @@ func setupCaching(provider string, systemPrompt string) []llms.CallOption {
TTL: "5m",
}),
)

case "gemini":
// Large content: use explicit caching
if len(systemPrompt) > 24000 {
Expand All @@ -1482,12 +1482,12 @@ func setupCaching(provider string, systemPrompt string) []llms.CallOption {
}
// Small content: rely on implicit caching with signature preservation
// Just ensure llms.WithReasoning() is used with gemini-3-flash-preview

case "openai":
// Nothing to configure - fully automatic
// Just monitor metrics to verify cache hits
}

return opts
}
```
Expand Down Expand Up @@ -1530,17 +1530,17 @@ aiParts := []llms.ContentPart{
```go
func buildUniversalAIMessage(choice *llms.ContentChoice) llms.MessageContent {
var parts []llms.ContentPart

// Add text with reasoning if present (safe for all providers)
if choice.Content != "" || choice.Reasoning != nil {
parts = append(parts,
llms.TextPartWithReasoning(choice.Content, choice.Reasoning),
)
}

// Add all tool calls
parts = append(parts, choice.ToolCalls...)

return llms.MessageContent{
Role: llms.ChatMessageTypeAI,
Parts: parts,
Expand Down Expand Up @@ -1575,17 +1575,17 @@ func extractReasoningContent(choice *llms.ContentChoice) string {
if choice.Reasoning != nil && choice.Reasoning.Content != "" {
return choice.Reasoning.Content
}

// Gemini: check first tool call
if len(choice.ToolCalls) > 0 && choice.ToolCalls[0].Reasoning != nil {
return choice.ToolCalls[0].Reasoning.Content
}

// Check if reasoning was used (even if content not returned)
if reasoningTokens, ok := choice.GenerationInfo["ReasoningTokens"].(int); ok && reasoningTokens > 0 {
return "[reasoning used but content not available]"
}

return ""
}
```
Expand Down Expand Up @@ -1627,21 +1627,21 @@ func (c *MultiProviderClient) SendMessage(
enableReasoning bool,
) (*llms.ContentResponse, error) {
opts := c.buildOptions(enableReasoning)

resp, err := c.llm.GenerateContent(ctx, messages, opts...)
if err != nil {
return nil, err
}

return resp, nil
}

func (c *MultiProviderClient) buildOptions(enableReasoning bool) []llms.CallOption {
var opts []llms.CallOption

if enableReasoning {
opts = append(opts, llms.WithReasoning(llms.ReasoningMedium, 2048))

// Provider-specific temperature
switch c.provider {
case "anthropic":
Expand All @@ -1654,10 +1654,10 @@ func (c *MultiProviderClient) buildOptions(enableReasoning bool) []llms.CallOpti
opts = append(opts, llms.WithTemperature(0.7))
}
}

// Provider-specific caching
opts = append(opts, c.setupCaching()...)

return opts
}

Expand Down Expand Up @@ -1689,10 +1689,10 @@ func (c *MultiProviderClient) ContinueConversation(
lastResponse *llms.ContentResponse,
) []llms.MessageContent {
choice := lastResponse.Choices[0]

// Build AI message in provider-agnostic way
var parts []llms.ContentPart

// Extract reasoning (location differs by provider)
var reasoning *reasoning.ContentReasoning
switch c.provider {
Expand All @@ -1705,15 +1705,15 @@ func (c *MultiProviderClient) ContinueConversation(
reasoning = choice.Reasoning
}
}

// Build parts list
if choice.Content != "" || reasoning != nil {
parts = append(parts,
llms.TextPartWithReasoning(choice.Content, reasoning),
)
}
parts = append(parts, choice.ToolCalls...)

return append(messages, llms.MessageContent{
Role: llms.ChatMessageTypeAI,
Parts: parts,
Expand Down Expand Up @@ -1859,7 +1859,7 @@ The library automatically handles these provider-specific edge cases:
---

**Version**: Based on APIs as of 2025-01
**Providers**:
**Providers**:
- Anthropic: Claude 3.7, Sonnet 4, Haiku 4.5+
- Gemini: gemini-2.5-flash, gemini-3-flash-preview
- OpenAI: o1, o3, o4, gpt-4.1+, and OpenAI-compatible backends
2 changes: 1 addition & 1 deletion backend/pkg/observability/langfuse/api/internal/caller.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type Caller struct {
retrier *Retrier
}

// CallerParams represents the parameters used to constrcut a new *Caller.
// CallerParams represents the parameters used to construct a new *Caller.
type CallerParams struct {
Client core.HTTPClient
MaxAttempts uint
Expand Down
4 changes: 2 additions & 2 deletions backend/pkg/server/models/assistants.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (a Assistant) Validate(db *gorm.DB) {
}
}

// CreateAssistant is model to contain assistant creation paylaod
// CreateAssistant is model to contain assistant creation payload
// nolint:lll
type CreateAssistant struct {
Input string `form:"input" json:"input" validate:"required" example:"user input for running assistant"`
Expand All @@ -96,7 +96,7 @@ func (ca CreateAssistant) Valid() error {
return validate.Struct(ca)
}

// PatchAssistant is model to contain assistant patching paylaod
// PatchAssistant is model to contain assistant patching payload
// nolint:lll
type PatchAssistant struct {
Action string `form:"action" json:"action" validate:"required,oneof=stop input" enums:"stop,input" default:"stop"`
Expand Down
4 changes: 2 additions & 2 deletions backend/pkg/server/models/flows.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (f Flow) Validate(db *gorm.DB) {
}
}

// CreateFlow is model to contain flow creation paylaod
// CreateFlow is model to contain flow creation payload
// nolint:lll
type CreateFlow struct {
Input string `form:"input" json:"input" validate:"required" example:"user input for first task in the flow"`
Expand All @@ -94,7 +94,7 @@ func (cf CreateFlow) Valid() error {
return validate.Struct(cf)
}

// PatchFlow is model to contain flow patching paylaod
// PatchFlow is model to contain flow patching payload
// nolint:lll
type PatchFlow struct {
Action string `form:"action" json:"action" validate:"required,oneof=stop finish input rename report" enums:"stop,finish,input,rename,report" default:"stop"`
Expand Down
2 changes: 1 addition & 1 deletion backend/pkg/server/models/prompts.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (p Prompt) Validate(db *gorm.DB) {
}
}

// PatchPrompt is model to contain prompt patching paylaod
// PatchPrompt is model to contain prompt patching payload
type PatchPrompt struct {
Prompt string `form:"prompt" json:"prompt" validate:"required"`
}
Expand Down
8 changes: 4 additions & 4 deletions backend/pkg/server/rdb/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (q *TableQuery) Init(table string, sqlMappers map[string]any) error {
switch t := v.(type) {
case string:
t = q.DoConditionFormat(t)
if isNumbericField(k) {
if isNumericField(k) {
q.sqlMappers[k] = t
} else {
q.sqlMappers[k] = "LOWER(" + t + "::text)"
Expand Down Expand Up @@ -239,12 +239,12 @@ func (q *TableQuery) DataFilter() func(db *gorm.DB) *gorm.DB {
switch f.Operator {
case "<", "<=", ">=", ">", "=", "!=", "in":
case "not like":
if isNumbericField(f.Field) {
if isNumericField(f.Field) {
f.Operator = "!="
}
default:
f.Operator = "like"
if isNumbericField(f.Field) {
if isNumericField(f.Field) {
f.Operator = "="
}
}
Expand Down Expand Up @@ -383,6 +383,6 @@ func MakeUuidStrFromHash(hash string) (string, error) {
return userIdUuid.String(), nil
}

func isNumbericField(field string) bool {
func isNumericField(field string) bool {
return strings.HasSuffix(field, "_id") || strings.HasSuffix(field, "_at") || field == "id"
}
2 changes: 1 addition & 1 deletion backend/pkg/templates/validator/testdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ func createBarrierTools() []tools.FunctionInfo {
for toolName, toolType := range toolsMapping {
if toolType == tools.BarrierToolType {
if def, ok := registryDefinitions[toolName]; ok {
// Convert parameters to JSON schema (simplified version of converToJSONSchema)
// Convert parameters to JSON schema (simplified version of convertToJSONSchema)
schemaJSON, err := json.Marshal(def.Parameters)
if err != nil {
continue
Expand Down
Loading