diff --git a/agent/assistant/assistant.go b/agent/assistant/assistant.go index 3e385256..5336ec15 100644 --- a/agent/assistant/assistant.go +++ b/agent/assistant/assistant.go @@ -349,6 +349,54 @@ func (ast *Assistant) Clone() *Assistant { return clone } +// GetInfo returns the basic info of the assistant with optional locale +func (ast *Assistant) GetInfo(locale ...string) *store.AssistantInfo { + if ast == nil { + return nil + } + + loc := "" + if len(locale) > 0 { + loc = locale[0] + } + + info := &store.AssistantInfo{ + AssistantID: ast.ID, + Avatar: ast.Avatar, + } + + // Apply i18n translation if locale is provided + if loc != "" { + info.Name = ast.GetName(loc) + info.Description = ast.GetDescription(loc) + } else { + info.Name = ast.Name + info.Description = ast.Description + } + + return info +} + +// GetInfoByIDs retrieves basic info for multiple assistants by their IDs +// Returns a map of assistant_id -> AssistantInfo +func GetInfoByIDs(ids []string, locale ...string) map[string]*store.AssistantInfo { + result := make(map[string]*store.AssistantInfo) + + if len(ids) == 0 { + return result + } + + for _, id := range ids { + ast, err := Get(id) + if err != nil || ast == nil { + continue + } + result[id] = ast.GetInfo(locale...) + } + + return result +} + // Update updates the assistant properties func (ast *Assistant) Update(data map[string]interface{}) error { if ast == nil { diff --git a/agent/assistant/chat.go b/agent/assistant/chat.go index 6a3fa892..1058c7f6 100644 --- a/agent/assistant/chat.go +++ b/agent/assistant/chat.go @@ -243,14 +243,16 @@ func (ast *Assistant) InitBuffer(ctx *agentcontext.Context) { requestID = uuid.New().String() } - // Get connector from options + // Get connector and mode from options connector := "" + mode := "" if ctx.Stack.Options != nil { connector = ctx.Stack.Options.Connector + mode = ctx.Stack.Options.Mode } - ctx.Buffer = agentcontext.NewChatBuffer(ctx.ChatID, requestID, ast.ID, connector) - log.Trace("[CHAT] Buffer initialized: chatID=%s, requestID=%s, assistantID=%s, connector=%s", ctx.ChatID, requestID, ast.ID, connector) + ctx.Buffer = agentcontext.NewChatBuffer(ctx.ChatID, requestID, ast.ID, connector, mode) + log.Trace("[CHAT] Buffer initialized: chatID=%s, requestID=%s, assistantID=%s, connector=%s, mode=%s", ctx.ChatID, requestID, ast.ID, connector, mode) } // BufferUserInput adds user input messages to the buffer @@ -341,7 +343,7 @@ func (ast *Assistant) FlushBuffer(ctx *agentcontext.Context, finalStatus string, } } - // 2. Update chat last_message_at and last_connector + // 2. Update chat last_message_at, last_connector, and last_mode if len(messages) > 0 { now := time.Now() updates := map[string]interface{}{ @@ -351,6 +353,10 @@ func (ast *Assistant) FlushBuffer(ctx *agentcontext.Context, finalStatus string, if connector := ctx.Buffer.Connector(); connector != "" { updates["last_connector"] = connector } + // Also update last_mode if available + if mode := ctx.Buffer.Mode(); mode != "" { + updates["last_mode"] = mode + } if updateErr := chatStore.UpdateChat(ctx.ChatID, updates); updateErr != nil { log.Trace("[CHAT] Failed to update chat: %v", updateErr) } @@ -388,6 +394,7 @@ func (ast *Assistant) convertBufferedMessages(buffered []*agentcontext.BufferedM ThreadID: msg.ThreadID, AssistantID: msg.AssistantID, Connector: msg.Connector, + Mode: msg.Mode, Sequence: msg.Sequence, Metadata: msg.Metadata, CreatedAt: msg.CreatedAt, @@ -454,7 +461,6 @@ func (ast *Assistant) EnsureChat(ctx *agentcontext.Context) error { chat := &storetypes.Chat{ ChatID: ctx.ChatID, AssistantID: ast.ID, - Mode: "chat", Status: "active", Share: "private", Sort: 0, @@ -487,6 +493,15 @@ func GetChatStore() storetypes.ChatStore { return storage } +// GetStore returns the full store instance (implements both ChatStore and AssistantStore) +// Returns nil if storage is not configured +func GetStore() storetypes.Store { + if storage == nil { + return nil + } + return storage +} + // ============================================================================= // Deprecated methods (kept for compatibility) // ============================================================================= diff --git a/agent/assistant/chat_test.go b/agent/assistant/chat_test.go index 85d19669..0e0a32d5 100644 --- a/agent/assistant/chat_test.go +++ b/agent/assistant/chat_test.go @@ -571,7 +571,6 @@ func TestFlushBuffer(t *testing.T) { err := chatStore.CreateChat(&storetypes.Chat{ ChatID: chatID, AssistantID: ast.ID, - Mode: "chat", Status: "active", Share: "private", CreatedAt: time.Now(), @@ -620,7 +619,6 @@ func TestFlushBuffer(t *testing.T) { err := chatStore.CreateChat(&storetypes.Chat{ ChatID: chatID, AssistantID: ast.ID, - Mode: "chat", Status: "active", Share: "private", CreatedAt: time.Now(), @@ -670,7 +668,6 @@ func TestFlushBuffer(t *testing.T) { err := chatStore.CreateChat(&storetypes.Chat{ ChatID: chatID, AssistantID: ast.ID, - Mode: "chat", Status: "active", Share: "private", CreatedAt: time.Now(), @@ -696,6 +693,71 @@ func TestFlushBuffer(t *testing.T) { chatStore.DeleteChat(chatID) t.Logf("✓ Buffer flushed on interrupt: resume records saved with interrupted status") }) + + t.Run("FlushWithModeAndConnector", func(t *testing.T) { + chatID := fmt.Sprintf("test_flush_mode_%s", uuid.New().String()[:8]) + ctx := agentcontext.New(context.Background(), nil, chatID) + ctx.Space = plan.NewMemorySharedSpace() + + // Enter stack with connector and mode options + opts := &agentcontext.Options{ + Connector: "deepseek.v3", + Mode: "task", + } + _, _, done := agentcontext.EnterStack(ctx, ast.ID, opts) + defer done() + ast.InitBuffer(ctx) + + // Verify buffer has correct connector and mode + require.NotNil(t, ctx.Buffer, "Buffer should be initialized") + assert.Equal(t, "deepseek.v3", ctx.Buffer.Connector(), "Buffer should have connector set") + assert.Equal(t, "task", ctx.Buffer.Mode(), "Buffer should have mode set") + + // Ensure chat exists + err := chatStore.CreateChat(&storetypes.Chat{ + ChatID: chatID, + AssistantID: ast.ID, + Status: "active", + Share: "private", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }) + require.NoError(t, err) + + // Add some messages to buffer + ctx.Buffer.AddUserInput("Test question for mode", "") + ctx.Buffer.AddAssistantMessage("M1", "text", map[string]interface{}{"content": "Test answer with mode"}, "", "", ast.ID, nil) + + // Flush buffer + ast.FlushBuffer(ctx, agentcontext.StepStatusCompleted, nil) + + // Verify messages were saved with connector and mode + messages, err := chatStore.GetMessages(chatID, storetypes.MessageFilter{}) + assert.NoError(t, err) + assert.Len(t, messages, 2, "Should have 2 messages saved") + + // Assistant message should have connector and mode + var assistantMsg *storetypes.Message + for _, msg := range messages { + if msg.Role == "assistant" { + assistantMsg = msg + break + } + } + require.NotNil(t, assistantMsg, "Should find assistant message") + assert.Equal(t, "deepseek.v3", assistantMsg.Connector, "Message should have connector") + assert.Equal(t, "task", assistantMsg.Mode, "Message should have mode") + + // Verify chat was updated with last_connector and last_mode + chat, err := chatStore.GetChat(chatID) + assert.NoError(t, err) + assert.Equal(t, "deepseek.v3", chat.LastConnector, "Chat should have last_connector updated") + assert.Equal(t, "task", chat.LastMode, "Chat should have last_mode updated") + + // Cleanup + chatStore.DeleteChat(chatID) + t.Logf("✓ Buffer flushed with mode and connector: connector=%s, mode=%s", chat.LastConnector, chat.LastMode) + }) } func TestEnsureChat(t *testing.T) { @@ -741,7 +803,6 @@ func TestEnsureChat(t *testing.T) { ChatID: chatID, AssistantID: ast.ID, Title: "Existing Chat", - Mode: "chat", Status: "active", Share: "private", CreatedAt: time.Now(), diff --git a/agent/context/buffer.go b/agent/context/buffer.go index f59f3231..3659be4f 100644 --- a/agent/context/buffer.go +++ b/agent/context/buffer.go @@ -19,6 +19,7 @@ type ChatBuffer struct { requestID string assistantID string connector string // Current connector ID (for data analysis) + mode string // Current chat mode (chat or task) // Message buffer messages []*BufferedMessage @@ -47,6 +48,7 @@ type BufferedMessage struct { ThreadID string `json:"thread_id,omitempty"` AssistantID string `json:"assistant_id,omitempty"` Connector string `json:"connector,omitempty"` // Connector ID used for this message + Mode string `json:"mode,omitempty"` // Chat mode used for this message (chat or task) Sequence int `json:"sequence"` Metadata map[string]interface{} `json:"metadata,omitempty"` CreatedAt time.Time `json:"created_at"` @@ -97,12 +99,13 @@ const ( ) // NewChatBuffer creates a new chat buffer -func NewChatBuffer(chatID, requestID, assistantID, connector string) *ChatBuffer { +func NewChatBuffer(chatID, requestID, assistantID, connector, mode string) *ChatBuffer { return &ChatBuffer{ chatID: chatID, requestID: requestID, assistantID: assistantID, connector: connector, + mode: mode, messages: make([]*BufferedMessage, 0), steps: make([]*BufferedStep, 0), } @@ -135,6 +138,11 @@ func (b *ChatBuffer) AddMessage(msg *BufferedMessage) { msg.CreatedAt = time.Now() } + // Set mode from buffer if not provided + if msg.Mode == "" && b.mode != "" { + msg.Mode = b.mode + } + // Auto-increment sequence b.msgSequence++ msg.Sequence = b.msgSequence @@ -447,6 +455,18 @@ func (b *ChatBuffer) SetConnector(connector string) { b.connector = connector } +// Mode returns the current chat mode +func (b *ChatBuffer) Mode() string { + return b.mode +} + +// SetMode updates the chat mode (when user switches mode) +func (b *ChatBuffer) SetMode(mode string) { + b.mu.Lock() + defer b.mu.Unlock() + b.mode = mode +} + // ============================================================================= // Helper Functions // ============================================================================= diff --git a/agent/context/buffer_test.go b/agent/context/buffer_test.go index dbfb07e5..ed1200ec 100644 --- a/agent/context/buffer_test.go +++ b/agent/context/buffer_test.go @@ -17,7 +17,7 @@ import ( func TestBufferNewChatBuffer(t *testing.T) { t.Run("CreateWithAllFields", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-123", "req-456", "assistant-789", "") + buffer := context.NewChatBuffer("chat-123", "req-456", "assistant-789", "", "") assert.NotNil(t, buffer) assert.Equal(t, "chat-123", buffer.ChatID()) @@ -29,7 +29,7 @@ func TestBufferNewChatBuffer(t *testing.T) { }) t.Run("CreateWithEmptyFields", func(t *testing.T) { - buffer := context.NewChatBuffer("", "", "", "") + buffer := context.NewChatBuffer("", "", "", "", "") assert.NotNil(t, buffer) assert.Empty(t, buffer.ChatID()) @@ -44,7 +44,7 @@ func TestBufferNewChatBuffer(t *testing.T) { func TestBufferAddMessage(t *testing.T) { t.Run("AddSingleMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") msg := &context.BufferedMessage{ Role: "assistant", @@ -65,7 +65,7 @@ func TestBufferAddMessage(t *testing.T) { }) t.Run("AddMultipleMessages", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") for i := 0; i < 5; i++ { buffer.AddMessage(&context.BufferedMessage{ @@ -85,14 +85,14 @@ func TestBufferAddMessage(t *testing.T) { }) t.Run("AddNilMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") buffer.AddMessage(nil) assert.Equal(t, 0, buffer.GetMessageCount()) }) t.Run("AddMessageWithExistingID", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "") + buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "", "") msg := &context.BufferedMessage{ MessageID: "custom-id-123", @@ -107,7 +107,7 @@ func TestBufferAddMessage(t *testing.T) { }) t.Run("AddMessageWithExistingTimestamp", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-5", "req-5", "assistant-5", "") + buffer := context.NewChatBuffer("chat-5", "req-5", "assistant-5", "", "") customTime := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC) msg := &context.BufferedMessage{ @@ -125,7 +125,7 @@ func TestBufferAddMessage(t *testing.T) { func TestBufferAddUserInput(t *testing.T) { t.Run("AddStringContent", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") buffer.AddUserInput("What is the weather?", "") messages := buffer.GetMessages() @@ -137,7 +137,7 @@ func TestBufferAddUserInput(t *testing.T) { }) t.Run("AddUserInputWithName", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") buffer.AddUserInput("Hello", "John") messages := buffer.GetMessages() @@ -146,7 +146,7 @@ func TestBufferAddUserInput(t *testing.T) { }) t.Run("AddComplexContent", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") complexContent := []map[string]interface{}{ {"type": "text", "text": "Look at this image"}, {"type": "image_url", "image_url": map[string]string{"url": "https://example.com/image.jpg"}}, @@ -163,7 +163,7 @@ func TestBufferAddUserInput(t *testing.T) { func TestBufferAddAssistantMessage(t *testing.T) { t.Run("AddTextMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") buffer.AddAssistantMessage( "M1", "text", @@ -186,7 +186,7 @@ func TestBufferAddAssistantMessage(t *testing.T) { }) t.Run("SkipEventMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") buffer.AddAssistantMessage( "E1", "event", @@ -199,7 +199,7 @@ func TestBufferAddAssistantMessage(t *testing.T) { }) t.Run("AddRetrievalMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") buffer.AddAssistantMessage( "M2", "retrieval", @@ -218,7 +218,7 @@ func TestBufferAddAssistantMessage(t *testing.T) { }) t.Run("AddToolCallMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "") + buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "", "") buffer.AddAssistantMessage( "M3", "tool_call", @@ -236,7 +236,7 @@ func TestBufferAddAssistantMessage(t *testing.T) { }) t.Run("AddCustomTypeMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-5", "req-5", "assistant-5", "") + buffer := context.NewChatBuffer("chat-5", "req-5", "assistant-5", "", "") buffer.AddAssistantMessage( "M4", "custom_chart", @@ -255,7 +255,7 @@ func TestBufferAddAssistantMessage(t *testing.T) { func TestBufferGetMessages(t *testing.T) { t.Run("GetMessagesReturnsSliceCopy", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") buffer.AddUserInput("Hello", "") messages1 := buffer.GetMessages() @@ -268,7 +268,7 @@ func TestBufferGetMessages(t *testing.T) { }) t.Run("GetEmptyMessages", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") messages := buffer.GetMessages() assert.NotNil(t, messages) @@ -277,7 +277,7 @@ func TestBufferGetMessages(t *testing.T) { } func TestBufferGetMessageCount(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") assert.Equal(t, 0, buffer.GetMessageCount()) buffer.AddUserInput("Message 1", "") @@ -293,7 +293,7 @@ func TestBufferGetMessageCount(t *testing.T) { func TestBufferBeginStep(t *testing.T) { t.Run("BeginStepWithStack", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") stack := &context.Stack{ ID: "stack-123", @@ -319,7 +319,7 @@ func TestBufferBeginStep(t *testing.T) { }) t.Run("BeginStepWithNilStack", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") step := buffer.BeginStep(context.StepTypeInput, nil, nil) @@ -330,7 +330,7 @@ func TestBufferBeginStep(t *testing.T) { }) t.Run("BeginMultipleSteps", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") step1 := buffer.BeginStep(context.StepTypeInput, nil, nil) step2 := buffer.BeginStep(context.StepTypeHookCreate, nil, nil) @@ -345,7 +345,7 @@ func TestBufferBeginStep(t *testing.T) { }) t.Run("BeginStepWithSpaceSnapshot", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "") + buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "", "") // Set space snapshot before beginning step buffer.SetSpaceSnapshot(map[string]interface{}{ @@ -363,7 +363,7 @@ func TestBufferBeginStep(t *testing.T) { func TestBufferCompleteStep(t *testing.T) { t.Run("CompleteCurrentStep", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") buffer.BeginStep(context.StepTypeLLM, map[string]interface{}{"prompt": "Hello"}, nil) buffer.CompleteStep(map[string]interface{}{"response": "Hi there!"}) @@ -376,7 +376,7 @@ func TestBufferCompleteStep(t *testing.T) { }) t.Run("CompleteWithNoCurrentStep", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") // Should not panic buffer.CompleteStep(map[string]interface{}{"response": "test"}) @@ -384,7 +384,7 @@ func TestBufferCompleteStep(t *testing.T) { }) t.Run("CompleteMultipleStepsSequentially", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") buffer.BeginStep(context.StepTypeInput, nil, nil) buffer.CompleteStep(map[string]interface{}{"done": true}) @@ -405,7 +405,7 @@ func TestBufferCompleteStep(t *testing.T) { func TestBufferFailCurrentStep(t *testing.T) { t.Run("FailWithError", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") buffer.BeginStep(context.StepTypeLLM, nil, nil) buffer.FailCurrentStep(context.ResumeStatusFailed, fmt.Errorf("API error: rate limit exceeded")) @@ -417,7 +417,7 @@ func TestBufferFailCurrentStep(t *testing.T) { }) t.Run("FailWithInterrupted", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") buffer.BeginStep(context.StepTypeLLM, nil, nil) buffer.FailCurrentStep(context.ResumeStatusInterrupted, nil) @@ -429,7 +429,7 @@ func TestBufferFailCurrentStep(t *testing.T) { }) t.Run("FailAlreadyCompletedStep", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") buffer.BeginStep(context.StepTypeLLM, nil, nil) buffer.CompleteStep(map[string]interface{}{"done": true}) @@ -443,7 +443,7 @@ func TestBufferFailCurrentStep(t *testing.T) { }) t.Run("FailWithNoCurrentStep", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "") + buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "", "") // Should not panic buffer.FailCurrentStep(context.ResumeStatusFailed, fmt.Errorf("error")) @@ -452,12 +452,12 @@ func TestBufferFailCurrentStep(t *testing.T) { func TestBufferGetCurrentStep(t *testing.T) { t.Run("NoCurrentStep", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") assert.Nil(t, buffer.GetCurrentStep()) }) t.Run("HasCurrentStep", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") buffer.BeginStep(context.StepTypeLLM, nil, nil) current := buffer.GetCurrentStep() @@ -466,7 +466,7 @@ func TestBufferGetCurrentStep(t *testing.T) { }) t.Run("CurrentStepClearedAfterComplete", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") buffer.BeginStep(context.StepTypeLLM, nil, nil) buffer.CompleteStep(nil) @@ -476,7 +476,7 @@ func TestBufferGetCurrentStep(t *testing.T) { func TestBufferGetStepsForResume(t *testing.T) { t.Run("CompletedSuccessfully", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") buffer.BeginStep(context.StepTypeInput, nil, nil) buffer.CompleteStep(nil) @@ -489,7 +489,7 @@ func TestBufferGetStepsForResume(t *testing.T) { }) t.Run("FailedRequest", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") buffer.BeginStep(context.StepTypeInput, nil, nil) buffer.CompleteStep(nil) @@ -505,7 +505,7 @@ func TestBufferGetStepsForResume(t *testing.T) { }) t.Run("InterruptedRequest", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") buffer.BeginStep(context.StepTypeInput, nil, nil) buffer.CompleteStep(nil) @@ -523,7 +523,7 @@ func TestBufferGetStepsForResume(t *testing.T) { func TestBufferGetAllSteps(t *testing.T) { t.Run("GetStepsReturnsSliceCopy", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") buffer.BeginStep(context.StepTypeLLM, nil, nil) steps1 := buffer.GetAllSteps() @@ -535,7 +535,7 @@ func TestBufferGetAllSteps(t *testing.T) { }) t.Run("GetEmptySteps", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") steps := buffer.GetAllSteps() assert.NotNil(t, steps) @@ -549,7 +549,7 @@ func TestBufferGetAllSteps(t *testing.T) { func TestBufferSpaceSnapshot(t *testing.T) { t.Run("SetAndGetSnapshot", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") snapshot := map[string]interface{}{ "user_id": "user-123", @@ -566,7 +566,7 @@ func TestBufferSpaceSnapshot(t *testing.T) { }) t.Run("SnapshotIsCopy", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "") + buffer := context.NewChatBuffer("chat-2", "req-2", "assistant-2", "", "") original := map[string]interface{}{"key": "original"} buffer.SetSpaceSnapshot(original) @@ -580,7 +580,7 @@ func TestBufferSpaceSnapshot(t *testing.T) { }) t.Run("GetSnapshotReturnsCopy", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "") + buffer := context.NewChatBuffer("chat-3", "req-3", "assistant-3", "", "") buffer.SetSpaceSnapshot(map[string]interface{}{"key": "value"}) retrieved1 := buffer.GetSpaceSnapshot() @@ -591,13 +591,13 @@ func TestBufferSpaceSnapshot(t *testing.T) { }) t.Run("GetNilSnapshot", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "") + buffer := context.NewChatBuffer("chat-4", "req-4", "assistant-4", "", "") snapshot := buffer.GetSpaceSnapshot() assert.Nil(t, snapshot) }) t.Run("SetNilSnapshot", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-5", "req-5", "assistant-5", "") + buffer := context.NewChatBuffer("chat-5", "req-5", "assistant-5", "", "") buffer.SetSpaceSnapshot(map[string]interface{}{"key": "value"}) buffer.SetSpaceSnapshot(nil) @@ -612,7 +612,7 @@ func TestBufferSpaceSnapshot(t *testing.T) { func TestBufferIdentityMethods(t *testing.T) { t.Run("SetAssistantID", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-original", "") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-original", "", "") assert.Equal(t, "assistant-original", buffer.AssistantID()) @@ -621,22 +621,22 @@ func TestBufferIdentityMethods(t *testing.T) { }) t.Run("ChatID", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-test", "req-test", "assistant-test", "") + buffer := context.NewChatBuffer("chat-test", "req-test", "assistant-test", "", "") assert.Equal(t, "chat-test", buffer.ChatID()) }) t.Run("RequestID", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-test", "req-test", "assistant-test", "") + buffer := context.NewChatBuffer("chat-test", "req-test", "assistant-test", "", "") assert.Equal(t, "req-test", buffer.RequestID()) }) t.Run("Connector", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-test", "req-test", "assistant-test", "openai") + buffer := context.NewChatBuffer("chat-test", "req-test", "assistant-test", "openai", "") assert.Equal(t, "openai", buffer.Connector()) }) t.Run("SetConnector", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") assert.Equal(t, "openai", buffer.Connector()) // Simulate user switching connector mid-conversation @@ -645,14 +645,14 @@ func TestBufferIdentityMethods(t *testing.T) { }) t.Run("EmptyConnector", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-test", "req-test", "assistant-test", "") + buffer := context.NewChatBuffer("chat-test", "req-test", "assistant-test", "", "") assert.Equal(t, "", buffer.Connector()) }) } func TestBufferConnectorInMessages(t *testing.T) { t.Run("MessageInheritsConnector", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Add assistant message - should inherit connector from buffer buffer.AddAssistantMessage( @@ -668,7 +668,7 @@ func TestBufferConnectorInMessages(t *testing.T) { }) t.Run("MessageConnectorUpdatesWithBuffer", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // First message with openai buffer.AddAssistantMessage( @@ -696,7 +696,7 @@ func TestBufferConnectorInMessages(t *testing.T) { }) t.Run("UserInputDoesNotSetConnector", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // User input doesn't have connector (it's set by the system based on which model processes it) buffer.AddUserInput("Hello", "") @@ -709,7 +709,7 @@ func TestBufferConnectorInMessages(t *testing.T) { }) t.Run("MultipleConnectorSwitches", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Simulate a conversation with multiple connector switches connectors := []string{"openai", "anthropic", "openai", "google"} @@ -737,7 +737,7 @@ func TestBufferConnectorInMessages(t *testing.T) { // ============================================================================= func TestBufferConcurrentMessageOperations(t *testing.T) { - buffer := context.NewChatBuffer("chat-concurrent", "req-concurrent", "assistant-concurrent", "") + buffer := context.NewChatBuffer("chat-concurrent", "req-concurrent", "assistant-concurrent", "", "") var wg sync.WaitGroup numGoroutines := 100 @@ -770,7 +770,7 @@ func TestBufferConcurrentMessageOperations(t *testing.T) { } func TestBufferConcurrentStepOperations(t *testing.T) { - buffer := context.NewChatBuffer("chat-concurrent", "req-concurrent", "assistant-concurrent", "") + buffer := context.NewChatBuffer("chat-concurrent", "req-concurrent", "assistant-concurrent", "", "") var wg sync.WaitGroup numGoroutines := 50 @@ -794,7 +794,7 @@ func TestBufferConcurrentStepOperations(t *testing.T) { } func TestBufferConcurrentReadWrite(t *testing.T) { - buffer := context.NewChatBuffer("chat-rw", "req-rw", "assistant-rw", "") + buffer := context.NewChatBuffer("chat-rw", "req-rw", "assistant-rw", "", "") var wg sync.WaitGroup done := make(chan bool) @@ -868,7 +868,7 @@ func TestBufferStepStatusConstants(t *testing.T) { func TestBufferEdgeCases(t *testing.T) { t.Run("LargeNumberOfMessages", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-large", "req-large", "assistant-large", "") + buffer := context.NewChatBuffer("chat-large", "req-large", "assistant-large", "", "") // Add 10000 messages for i := 0; i < 10000; i++ { @@ -885,7 +885,7 @@ func TestBufferEdgeCases(t *testing.T) { }) t.Run("MessageWithEmptyProps", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-empty", "req-empty", "assistant-empty", "") + buffer := context.NewChatBuffer("chat-empty", "req-empty", "assistant-empty", "", "") buffer.AddMessage(&context.BufferedMessage{ Role: "assistant", @@ -899,7 +899,7 @@ func TestBufferEdgeCases(t *testing.T) { }) t.Run("StepWithEmptyInput", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-step", "req-step", "assistant-step", "") + buffer := context.NewChatBuffer("chat-step", "req-step", "assistant-step", "", "") step := buffer.BeginStep(context.StepTypeLLM, nil, nil) assert.Nil(t, step.Input) @@ -910,7 +910,7 @@ func TestBufferEdgeCases(t *testing.T) { }) t.Run("AllMessageTypes", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-types", "req-types", "assistant-types", "") + buffer := context.NewChatBuffer("chat-types", "req-types", "assistant-types", "", "") messageTypes := []string{ "text", "image", "loading", "tool_call", "tool_result", @@ -926,7 +926,7 @@ func TestBufferEdgeCases(t *testing.T) { }) t.Run("AllStepTypes", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-step-types", "req-step-types", "assistant-step-types", "") + buffer := context.NewChatBuffer("chat-step-types", "req-step-types", "assistant-step-types", "", "") stepTypes := []string{ context.StepTypeInput, context.StepTypeHookCreate, context.StepTypeLLM, @@ -949,7 +949,7 @@ func TestBufferEdgeCases(t *testing.T) { func TestBufferCompleteWorkflow(t *testing.T) { t.Run("SuccessfulChatFlow", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-workflow", "req-workflow", "assistant-main", "") + buffer := context.NewChatBuffer("chat-workflow", "req-workflow", "assistant-main", "", "") // 1. User input buffer.AddUserInput("What's the weather in San Francisco?", "John") @@ -993,7 +993,7 @@ func TestBufferCompleteWorkflow(t *testing.T) { }) t.Run("InterruptedChatFlow", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-interrupted", "req-interrupted", "assistant-main", "") + buffer := context.NewChatBuffer("chat-interrupted", "req-interrupted", "assistant-main", "", "") // Set space snapshot buffer.SetSpaceSnapshot(map[string]interface{}{ @@ -1024,7 +1024,7 @@ func TestBufferCompleteWorkflow(t *testing.T) { }) t.Run("A2ACallWithDelegation", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-a2a", "req-a2a", "assistant-main", "") + buffer := context.NewChatBuffer("chat-a2a", "req-a2a", "assistant-main", "", "") mainStack := &context.Stack{ID: "stack-main", Depth: 0} childStack := &context.Stack{ID: "stack-child", ParentID: "stack-main", Depth: 1} @@ -1060,7 +1060,7 @@ func TestBufferCompleteWorkflow(t *testing.T) { }) t.Run("ConcurrentAgentCalls", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-concurrent-a2a", "req-concurrent-a2a", "assistant-main", "") + buffer := context.NewChatBuffer("chat-concurrent-a2a", "req-concurrent-a2a", "assistant-main", "", "") // Main assistant spawns multiple concurrent calls buffer.BeginStep(context.StepTypeInput, nil, nil) @@ -1105,7 +1105,7 @@ func TestBufferCompleteWorkflow(t *testing.T) { func TestBufferMessageSequence(t *testing.T) { t.Run("SequenceAutoIncrement", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-seq", "req-seq", "assistant-seq", "") + buffer := context.NewChatBuffer("chat-seq", "req-seq", "assistant-seq", "", "") for i := 0; i < 10; i++ { buffer.AddMessage(&context.BufferedMessage{ @@ -1121,7 +1121,7 @@ func TestBufferMessageSequence(t *testing.T) { }) t.Run("MixedMessageTypes", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-mixed", "req-mixed", "assistant-mixed", "") + buffer := context.NewChatBuffer("chat-mixed", "req-mixed", "assistant-mixed", "", "") buffer.AddUserInput("Hello", "") buffer.AddAssistantMessage("M1", "text", nil, "", "", "", nil) @@ -1142,7 +1142,7 @@ func TestBufferMessageSequence(t *testing.T) { func TestBufferStepSequence(t *testing.T) { t.Run("SequenceAutoIncrement", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-step-seq", "req-step-seq", "assistant-step-seq", "") + buffer := context.NewChatBuffer("chat-step-seq", "req-step-seq", "assistant-step-seq", "", "") for i := 0; i < 5; i++ { buffer.BeginStep(context.StepTypeLLM, nil, nil) @@ -1163,10 +1163,10 @@ func TestBufferStepSequence(t *testing.T) { func TestBufferMultipleRequests(t *testing.T) { t.Run("NewBufferPerRequest", func(t *testing.T) { // Simulate multiple requests with separate buffers - buffer1 := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "") + buffer1 := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "", "") buffer1.AddUserInput("Request 1", "") - buffer2 := context.NewChatBuffer("chat-1", "req-2", "assistant-1", "") + buffer2 := context.NewChatBuffer("chat-1", "req-2", "assistant-1", "", "") buffer2.AddUserInput("Request 2", "") // Buffers should be independent @@ -1187,7 +1187,7 @@ func TestBufferMultipleRequests(t *testing.T) { func TestBufferStreamingMessage(t *testing.T) { t.Run("AddStreamingMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") buffer.AddStreamingMessage( "msg-stream-1", @@ -1211,7 +1211,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("AppendMessageContent", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Add streaming message buffer.AddStreamingMessage( @@ -1235,7 +1235,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("AppendToNonExistentMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Try to append to non-existent message ok := buffer.AppendMessageContent("non-existent", "content") @@ -1243,7 +1243,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("AppendToCompletedMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Add and complete streaming message buffer.AddStreamingMessage( @@ -1260,7 +1260,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("CompleteStreamingMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Add streaming message buffer.AddStreamingMessage( @@ -1289,7 +1289,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("CompleteNonExistentMessage", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") content, ok := buffer.CompleteStreamingMessage("non-existent") assert.False(t, ok) @@ -1297,7 +1297,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("StreamingMessageWorkflow", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "deepseek") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "deepseek", "") // Simulate a typical streaming workflow: // 1. SendStream sends initial content @@ -1332,7 +1332,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("MixedStreamingAndRegularMessages", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Add user input (regular) buffer.AddUserInput("Hello", "user1") @@ -1366,7 +1366,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("StreamingMessageWithEmptyInitialContent", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Add streaming message with nil props buffer.AddStreamingMessage( @@ -1386,7 +1386,7 @@ func TestBufferStreamingMessage(t *testing.T) { }) t.Run("ConcurrentStreamingOperations", func(t *testing.T) { - buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai") + buffer := context.NewChatBuffer("chat-1", "req-1", "assistant-1", "openai", "") // Add streaming message buffer.AddStreamingMessage( diff --git a/agent/context/context.go b/agent/context/context.go index b5d0496e..a3d383b2 100644 --- a/agent/context/context.go +++ b/agent/context/context.go @@ -399,8 +399,8 @@ func (ctx *Context) GetMessageMetadata(messageID string) *MessageMetadata { // InitBuffer initializes the chat buffer for this context // Should be called at the start of Stream() to begin buffering messages and steps -func (ctx *Context) InitBuffer(assistantID, connector string) *ChatBuffer { - ctx.Buffer = NewChatBuffer(ctx.ChatID, ctx.RequestID(), assistantID, connector) +func (ctx *Context) InitBuffer(assistantID, connector, mode string) *ChatBuffer { + ctx.Buffer = NewChatBuffer(ctx.ChatID, ctx.RequestID(), assistantID, connector, mode) return ctx.Buffer } diff --git a/agent/context/openapi.go b/agent/context/openapi.go index 8f5f61fd..7ffa087b 100644 --- a/agent/context/openapi.go +++ b/agent/context/openapi.go @@ -67,6 +67,7 @@ func GetCompletionRequest(c *gin.Context, cache store.Store) (*CompletionRequest opts := &Options{ Context: c.Request.Context(), Skip: GetSkip(c, completionReq), + Mode: GetMode(c, completionReq), } // Try to extract custom connector from model field @@ -377,6 +378,33 @@ func GetRoute(c *gin.Context, req *CompletionRequest) string { return "" } +// GetMode extracts mode from request with priority: +// 1. Query parameter "mode" +// 2. Header "X-Yao-Mode" +// 3. CompletionRequest metadata "mode" (from payload) +func GetMode(c *gin.Context, req *CompletionRequest) string { + // Priority 1: Query parameter + if mode := c.Query("mode"); mode != "" { + return mode + } + + // Priority 2: Header + if mode := c.GetHeader("X-Yao-Mode"); mode != "" { + return mode + } + + // Priority 3: From CompletionRequest metadata + if req != nil && req.Metadata != nil { + if mode, ok := req.Metadata["mode"]; ok { + if modeStr, ok := mode.(string); ok && modeStr != "" { + return modeStr + } + } + } + + return "" +} + // GetSkip extracts skip configuration from request with priority: // 1. CompletionRequest.Skip (from payload body) - Priority // 2. Individual query parameters: "skip_history", "skip_trace" diff --git a/agent/context/openapi_test.go b/agent/context/openapi_test.go index d7829b22..639b55a4 100644 --- a/agent/context/openapi_test.go +++ b/agent/context/openapi_test.go @@ -1145,3 +1145,103 @@ func TestGetSkip_FromBodyViaParseRequest(t *testing.T) { t.Error("Expected GetSkip to return Trace=false") } } + +func TestGetMode_FromQuery(t *testing.T) { + test.Prepare(t, config.Conf) + defer test.Clean() + + gin.SetMode(gin.TestMode) + + req := httptest.NewRequest("GET", "/chat/completions?mode=task", nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Request = req + + mode := GetMode(c, nil) + if mode != "task" { + t.Errorf("Expected mode 'task' from query, got '%s'", mode) + } +} + +func TestGetMode_FromHeader(t *testing.T) { + test.Prepare(t, config.Conf) + defer test.Clean() + + gin.SetMode(gin.TestMode) + + req := httptest.NewRequest("GET", "/chat/completions", nil) + req.Header.Set("X-Yao-Mode", "chat") + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Request = req + + mode := GetMode(c, nil) + if mode != "chat" { + t.Errorf("Expected mode 'chat' from header, got '%s'", mode) + } +} + +func TestGetMode_FromMetadata(t *testing.T) { + test.Prepare(t, config.Conf) + defer test.Clean() + + gin.SetMode(gin.TestMode) + + req := httptest.NewRequest("GET", "/chat/completions", nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Request = req + + completionReq := &CompletionRequest{ + Metadata: map[string]interface{}{ + "mode": "task", + }, + } + + mode := GetMode(c, completionReq) + if mode != "task" { + t.Errorf("Expected mode 'task' from metadata, got '%s'", mode) + } +} + +func TestGetMode_Priority(t *testing.T) { + test.Prepare(t, config.Conf) + defer test.Clean() + + gin.SetMode(gin.TestMode) + + // Query has highest priority + req := httptest.NewRequest("GET", "/chat/completions?mode=query_mode", nil) + req.Header.Set("X-Yao-Mode", "header_mode") + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Request = req + + completionReq := &CompletionRequest{ + Metadata: map[string]interface{}{ + "mode": "metadata_mode", + }, + } + + mode := GetMode(c, completionReq) + if mode != "query_mode" { + t.Errorf("Expected mode 'query_mode' (query has priority), got '%s'", mode) + } +} + +func TestGetMode_Empty(t *testing.T) { + test.Prepare(t, config.Conf) + defer test.Clean() + + gin.SetMode(gin.TestMode) + + req := httptest.NewRequest("GET", "/chat/completions", nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Request = req + + mode := GetMode(c, nil) + if mode != "" { + t.Errorf("Expected empty mode, got '%s'", mode) + } +} diff --git a/agent/store/CHAT_STORAGE_DESIGN.md b/agent/store/CHAT_STORAGE_DESIGN.md index dbdd9460..4e7248a1 100644 --- a/agent/store/CHAT_STORAGE_DESIGN.md +++ b/agent/store/CHAT_STORAGE_DESIGN.md @@ -92,7 +92,7 @@ Stores chat metadata and session information. | `title` | string(500) | Yes | - | Chat title | | `assistant_id` | string(200) | No | Yes | Associated assistant ID | | `last_connector` | string(200) | Yes | Yes | Last used connector ID | -| `mode` | string(50) | No | - | Chat mode (default: "chat") | +| `last_mode` | string(50) | Yes | - | Last used chat mode (chat/task) | | `status` | enum | No | Yes | Status: `active`, `archived` | | `public` | boolean | No | - | Whether shared across all teams | | `share` | enum | No | Yes | Sharing scope: `private`, `team` | @@ -141,23 +141,24 @@ Stores user-visible messages (both user input and assistant responses). **Table Name:** `agent_message` -| Column | Type | Nullable | Index | Description | -| -------------- | ----------- | -------- | ----- | ------------------------------------------ | -| `id` | ID | No | PK | Auto-increment primary key | -| `message_id` | string(64) | No | - | Message identifier (unique within request) | -| `chat_id` | string(64) | No | Yes | Parent chat ID | -| `request_id` | string(64) | Yes | Yes | Request ID for grouping | -| `role` | enum | No | Yes | Role: `user`, `assistant` | -| `type` | string(50) | No | - | Message type (text, image, loading, etc.) | -| `props` | json | No | - | Message properties (content, url, etc.) | -| `block_id` | string(64) | Yes | Yes | Block grouping ID | -| `thread_id` | string(64) | Yes | Yes | Thread grouping ID | -| `assistant_id` | string(200) | Yes | Yes | Assistant ID (join to get name/avatar) | -| `connector` | string(200) | Yes | Yes | Connector ID used for this message | -| `sequence` | integer | No | - | Message order within chat (in composite) | -| `metadata` | json | Yes | - | Additional metadata | -| `created_at` | timestamp | No | Yes | Creation timestamp | -| `updated_at` | timestamp | No | - | Last update timestamp | +| Column | Type | Nullable | Index | Description | +| -------------- | ----------- | -------- | ----- | ------------------------------------------- | +| `id` | ID | No | PK | Auto-increment primary key | +| `message_id` | string(64) | No | - | Message identifier (unique within request) | +| `chat_id` | string(64) | No | Yes | Parent chat ID | +| `request_id` | string(64) | Yes | Yes | Request ID for grouping | +| `role` | enum | No | Yes | Role: `user`, `assistant` | +| `type` | string(50) | No | - | Message type (text, image, loading, etc.) | +| `props` | json | No | - | Message properties (content, url, etc.) | +| `block_id` | string(64) | Yes | Yes | Block grouping ID | +| `thread_id` | string(64) | Yes | Yes | Thread grouping ID | +| `assistant_id` | string(200) | Yes | Yes | Assistant ID (join to get name/avatar) | +| `connector` | string(200) | Yes | Yes | Connector ID used for this message | +| `mode` | string(50) | Yes | - | Chat mode used for this message (chat/task) | +| `sequence` | integer | No | - | Message order within chat (in composite) | +| `metadata` | json | Yes | - | Additional metadata | +| `created_at` | timestamp | No | Yes | Creation timestamp | +| `updated_at` | timestamp | No | - | Last update timestamp | **Indexes:** @@ -171,6 +172,20 @@ Stores user-visible messages (both user input and assistant responses). | `idx_msg_thread` | `thread_id` | index | | `idx_msg_assistant` | `assistant_id` | index | +**Message Ordering:** + +Messages are ordered by `created_at` first, then by `sequence` within the same timestamp. This ensures correct chronological order when there are multiple requests with overlapping sequence numbers: + +```sql +ORDER BY created_at ASC, sequence ASC +``` + +**Why this ordering?** + +- `sequence` is assigned per-request, so different requests may have the same sequence numbers +- `created_at` groups messages by request time, ensuring messages from earlier requests appear first +- Within the same request (same `created_at`), `sequence` preserves the internal ordering + **Message Types:** All message types are stored, including built-in types and custom types. See `agent/output/BUILTIN_TYPES.md` for built-in Props structures. @@ -813,8 +828,8 @@ type Chat struct { ChatID string `json:"chat_id"` Title string `json:"title,omitempty"` AssistantID string `json:"assistant_id"` - LastConnector string `json:"last_connector,omitempty"` // Last used connector ID - Mode string `json:"mode"` + LastConnector string `json:"last_connector,omitempty"` // Last used connector ID (updated on each message) + LastMode string `json:"last_mode,omitempty"` // Last used chat mode (updated on each message) Status string `json:"status"` // "active" or "archived" Public bool `json:"public"` // Whether shared across all teams Share string `json:"share"` // "private" or "team" @@ -837,6 +852,7 @@ type Message struct { ThreadID string `json:"thread_id,omitempty"` AssistantID string `json:"assistant_id,omitempty"` Connector string `json:"connector,omitempty"` // Connector ID used for this message + Mode string `json:"mode,omitempty"` // Chat mode used for this message (chat or task) Sequence int `json:"sequence"` Metadata map[string]interface{} `json:"metadata,omitempty"` CreatedAt time.Time `json:"created_at"` @@ -1585,7 +1601,8 @@ GET /v1/chat/sessions/chat_123 "chat_id": "chat_123", "title": "Weather Query", "assistant_id": "weather_assistant", - "mode": "chat", + "last_connector": "deepseek.v3", + "last_mode": "chat", "status": "active", "public": false, "share": "private", diff --git a/agent/store/types/types.go b/agent/store/types/types.go index bf01251a..ef1e08a9 100644 --- a/agent/store/types/types.go +++ b/agent/store/types/types.go @@ -30,11 +30,11 @@ type Chat struct { Title string `json:"title,omitempty"` AssistantID string `json:"assistant_id"` LastConnector string `json:"last_connector,omitempty"` // Last used connector ID (updated on each message) - Mode string `json:"mode"` - Status string `json:"status"` // "active" or "archived" - Public bool `json:"public"` // Whether shared across all teams - Share string `json:"share"` // "private" or "team" - Sort int `json:"sort"` // Sort order for display + LastMode string `json:"last_mode,omitempty"` // Last used chat mode (updated on each message) + Status string `json:"status"` // "active" or "archived" + Public bool `json:"public"` // Whether shared across all teams + Share string `json:"share"` // "private" or "team" + Sort int `json:"sort"` // Sort order for display LastMessageAt *time.Time `json:"last_message_at,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"` CreatedAt time.Time `json:"created_at"` @@ -109,6 +109,7 @@ type Message struct { ThreadID string `json:"thread_id,omitempty"` AssistantID string `json:"assistant_id,omitempty"` Connector string `json:"connector,omitempty"` // Connector ID used for this message + Mode string `json:"mode,omitempty"` // Chat mode used for this message (chat or task) Sequence int `json:"sequence"` Metadata map[string]interface{} `json:"metadata,omitempty"` CreatedAt time.Time `json:"created_at"` @@ -198,6 +199,15 @@ type AssistantList struct { Total int `json:"total"` // Total number of items across all pages } +// AssistantInfo contains basic assistant information for display +// Used in chat history to show assistant details with i18n support +type AssistantInfo struct { + AssistantID string `json:"assistant_id"` + Name string `json:"name"` + Avatar string `json:"avatar,omitempty"` + Description string `json:"description,omitempty"` +} + // Tag represents a tag type Tag struct { Value string `json:"value"` diff --git a/agent/store/xun/chat.go b/agent/store/xun/chat.go index 72acaada..33749b0d 100644 --- a/agent/store/xun/chat.go +++ b/agent/store/xun/chat.go @@ -42,9 +42,6 @@ func (store *Xun) CreateChat(chat *types.Chat) error { } // Set defaults - if chat.Mode == "" { - chat.Mode = "chat" - } if chat.Status == "" { chat.Status = "active" } @@ -56,7 +53,6 @@ func (store *Xun) CreateChat(chat *types.Chat) error { data := map[string]interface{}{ "chat_id": chat.ChatID, "assistant_id": chat.AssistantID, - "mode": chat.Mode, "status": chat.Status, "public": chat.Public, "share": chat.Share, @@ -65,6 +61,11 @@ func (store *Xun) CreateChat(chat *types.Chat) error { "updated_at": time.Now(), } + // Handle last_mode (nullable) + if chat.LastMode != "" { + data["last_mode"] = chat.LastMode + } + // Handle nullable fields if chat.Title != "" { data["title"] = chat.Title @@ -72,6 +73,9 @@ func (store *Xun) CreateChat(chat *types.Chat) error { if chat.LastConnector != "" { data["last_connector"] = chat.LastConnector } + if chat.LastMode != "" { + data["last_mode"] = chat.LastMode + } if chat.LastMessageAt != nil { data["last_message_at"] = *chat.LastMessageAt } @@ -337,7 +341,7 @@ func (store *Xun) rowToChat(data map[string]interface{}) (*types.Chat, error) { Title: getString(data, "title"), AssistantID: getString(data, "assistant_id"), LastConnector: getString(data, "last_connector"), - Mode: getString(data, "mode"), + LastMode: getString(data, "last_mode"), Status: getString(data, "status"), Public: getBool(data, "public"), Share: getString(data, "share"), diff --git a/agent/store/xun/chat_test.go b/agent/store/xun/chat_test.go index 8f95cd2e..ac954d31 100644 --- a/agent/store/xun/chat_test.go +++ b/agent/store/xun/chat_test.go @@ -29,7 +29,6 @@ func TestCreateChat(t *testing.T) { chat := &types.Chat{ AssistantID: "test_assistant", Title: "Test Chat", - Mode: "chat", Status: "active", Share: "private", } @@ -55,7 +54,7 @@ func TestCreateChat(t *testing.T) { AssistantID: "test_assistant", LastConnector: "openai", Title: "Full Chat", - Mode: "task", + LastMode: "task", Status: "active", Public: true, Share: "team", @@ -84,8 +83,8 @@ func TestCreateChat(t *testing.T) { if retrieved.LastConnector != "openai" { t.Errorf("Expected last_connector 'openai', got '%s'", retrieved.LastConnector) } - if retrieved.Mode != "task" { - t.Errorf("Expected mode 'task', got '%s'", retrieved.Mode) + if retrieved.LastMode != "task" { + t.Errorf("Expected last_mode 'task', got '%s'", retrieved.LastMode) } if !retrieved.Public { t.Error("Expected public to be true") @@ -183,8 +182,9 @@ func TestCreateChat(t *testing.T) { t.Fatalf("Failed to retrieve chat: %v", err) } - if retrieved.Mode != "chat" { - t.Errorf("Expected default mode 'chat', got '%s'", retrieved.Mode) + // last_mode is nullable, so it should be empty by default + if retrieved.LastMode != "" { + t.Errorf("Expected default last_mode to be empty, got '%s'", retrieved.LastMode) } if retrieved.Status != "active" { t.Errorf("Expected default status 'active', got '%s'", retrieved.Status) @@ -1103,7 +1103,6 @@ func TestChatCompleteWorkflow(t *testing.T) { chat := &types.Chat{ AssistantID: "workflow_assistant", Title: "Workflow Test Chat", - Mode: "chat", Status: "active", } diff --git a/agent/store/xun/message.go b/agent/store/xun/message.go index f9d2a2af..d97e81fa 100644 --- a/agent/store/xun/message.go +++ b/agent/store/xun/message.go @@ -69,6 +69,7 @@ func (store *Xun) SaveMessages(chatID string, messages []*types.Message) error { "thread_id": nil, "assistant_id": nil, "connector": nil, + "mode": nil, "metadata": nil, "created_at": now, "updated_at": now, @@ -90,6 +91,9 @@ func (store *Xun) SaveMessages(chatID string, messages []*types.Message) error { if msg.Connector != "" { row["connector"] = msg.Connector } + if msg.Mode != "" { + row["mode"] = msg.Mode + } if msg.Metadata != nil { metadataJSON, err := jsoniter.MarshalToString(msg.Metadata) if err != nil { @@ -147,8 +151,8 @@ func (store *Xun) GetMessages(chatID string, filter types.MessageFilter) ([]*typ qb.Limit(1000000).Offset(filter.Offset) } - // Order by sequence - qb.OrderBy("sequence", "asc") + // Order by created_at first, then by sequence within the same request + qb.OrderBy("created_at", "asc").OrderBy("sequence", "asc") rows, err := qb.Get() if err != nil { @@ -332,6 +336,7 @@ func (store *Xun) rowToMessage(data map[string]interface{}) (*types.Message, err ThreadID: getString(data, "thread_id"), AssistantID: getString(data, "assistant_id"), Connector: getString(data, "connector"), + Mode: getString(data, "mode"), Sequence: getInt(data, "sequence"), } diff --git a/agent/store/xun/message_test.go b/agent/store/xun/message_test.go index 2093c512..6fcd63a8 100644 --- a/agent/store/xun/message_test.go +++ b/agent/store/xun/message_test.go @@ -282,6 +282,84 @@ func TestSaveMessages(t *testing.T) { t.Logf("Successfully saved and retrieved messages with different connectors") }) + t.Run("SaveMessageWithMode", func(t *testing.T) { + modeChat := &types.Chat{ + AssistantID: "test_assistant", + } + err := store.CreateChat(modeChat) + if err != nil { + t.Fatalf("Failed to create chat: %v", err) + } + defer store.DeleteChat(modeChat.ChatID) + + // Save messages with different modes + messages := []*types.Message{ + { + Role: "user", + Type: "user_input", + Props: map[string]interface{}{"content": "Hello in chat mode"}, + Sequence: 1, + Mode: "chat", + Connector: "deepseek.v3", + AssistantID: "test_assistant", + }, + { + Role: "assistant", + Type: "text", + Props: map[string]interface{}{"content": "Hi there in chat mode!"}, + Sequence: 2, + Mode: "chat", + Connector: "deepseek.v3", + AssistantID: "test_assistant", + }, + { + Role: "user", + Type: "user_input", + Props: map[string]interface{}{"content": "Now run a task"}, + Sequence: 3, + Mode: "task", + Connector: "deepseek.v3", + AssistantID: "test_assistant", + }, + { + Role: "assistant", + Type: "text", + Props: map[string]interface{}{"content": "Running task!"}, + Sequence: 4, + Mode: "task", + Connector: "deepseek.v3", + AssistantID: "test_assistant", + }, + } + + err = store.SaveMessages(modeChat.ChatID, messages) + if err != nil { + t.Fatalf("Failed to save messages: %v", err) + } + + // Retrieve and verify modes + retrieved, err := store.GetMessages(modeChat.ChatID, types.MessageFilter{}) + if err != nil { + t.Fatalf("Failed to get messages: %v", err) + } + + if len(retrieved) != 4 { + t.Fatalf("Expected 4 messages, got %d", len(retrieved)) + } + + // Verify each message has correct mode + for _, msg := range retrieved { + if msg.Sequence <= 2 && msg.Mode != "chat" { + t.Errorf("Expected mode 'chat' for sequence %d, got '%s'", msg.Sequence, msg.Mode) + } + if msg.Sequence > 2 && msg.Mode != "task" { + t.Errorf("Expected mode 'task' for sequence %d, got '%s'", msg.Sequence, msg.Mode) + } + } + + t.Logf("Successfully saved and retrieved messages with different modes") + }) + t.Run("SaveMessageWithEmptyConnector", func(t *testing.T) { emptyConnChat := &types.Chat{ AssistantID: "test_assistant", @@ -533,6 +611,127 @@ func TestGetMessages(t *testing.T) { t.Errorf("Expected 0 messages from non-existent chat, got %d", len(retrieved)) } }) + + t.Run("OrderByCreatedAtThenSequence", func(t *testing.T) { + // This test verifies that messages are ordered by created_at first, then by sequence + // This is important when there are multiple request_ids with overlapping sequence numbers + orderChat := &types.Chat{ + AssistantID: "test_assistant", + } + err := store.CreateChat(orderChat) + if err != nil { + t.Fatalf("Failed to create chat: %v", err) + } + defer store.DeleteChat(orderChat.ChatID) + + // Simulate two separate requests with overlapping sequence numbers + // SaveMessages uses time.Now() for created_at, so we need to call it twice + // with a small delay to ensure different timestamps + + // Request 1: sequences 1, 2 + req1Messages := []*types.Message{ + { + Role: "user", + Type: "user_input", + Props: map[string]interface{}{"content": "Request 1 - Message 1"}, + Sequence: 1, + RequestID: "order_req_001", + }, + { + Role: "assistant", + Type: "text", + Props: map[string]interface{}{"content": "Request 1 - Response 1"}, + Sequence: 2, + RequestID: "order_req_001", + }, + } + + err = store.SaveMessages(orderChat.ChatID, req1Messages) + if err != nil { + t.Fatalf("Failed to save request 1 messages: %v", err) + } + + // Delay to ensure different created_at timestamps + // Database timestamp precision may only be to second level + time.Sleep(1100 * time.Millisecond) + + // Request 2: sequences 1, 2 (same as request 1, but later created_at) + req2Messages := []*types.Message{ + { + Role: "user", + Type: "user_input", + Props: map[string]interface{}{"content": "Request 2 - Message 1"}, + Sequence: 1, // Same sequence as req1, but later created_at + RequestID: "order_req_002", + }, + { + Role: "assistant", + Type: "text", + Props: map[string]interface{}{"content": "Request 2 - Response 1"}, + Sequence: 2, // Same sequence as req1, but later created_at + RequestID: "order_req_002", + }, + } + + err = store.SaveMessages(orderChat.ChatID, req2Messages) + if err != nil { + t.Fatalf("Failed to save request 2 messages: %v", err) + } + + // Retrieve messages + retrieved, err := store.GetMessages(orderChat.ChatID, types.MessageFilter{}) + if err != nil { + t.Fatalf("Failed to get messages: %v", err) + } + + if len(retrieved) != 4 { + t.Fatalf("Expected 4 messages, got %d", len(retrieved)) + } + + // Verify order: should be chronological by created_at, then by sequence + // Messages from req_001 should come before req_002 + expectedOrder := []struct { + requestID string + sequence int + content string + }{ + {"order_req_001", 1, "Request 1 - Message 1"}, + {"order_req_001", 2, "Request 1 - Response 1"}, + {"order_req_002", 1, "Request 2 - Message 1"}, + {"order_req_002", 2, "Request 2 - Response 1"}, + } + + for i, expected := range expectedOrder { + msg := retrieved[i] + if msg.RequestID != expected.requestID { + t.Errorf("Message %d: expected RequestID '%s', got '%s'", i, expected.requestID, msg.RequestID) + } + if msg.Sequence != expected.sequence { + t.Errorf("Message %d: expected Sequence %d, got %d", i, expected.sequence, msg.Sequence) + } + content, _ := msg.Props["content"].(string) + if content != expected.content { + t.Errorf("Message %d: expected content '%s', got '%s'", i, expected.content, content) + } + } + + // Additional verification: ensure created_at is non-decreasing + for i := 1; i < len(retrieved); i++ { + if retrieved[i].CreatedAt.Before(retrieved[i-1].CreatedAt) { + t.Errorf("Message %d created_at (%v) is before message %d created_at (%v)", + i, retrieved[i].CreatedAt, i-1, retrieved[i-1].CreatedAt) + } + // If same created_at, sequence should be increasing + if retrieved[i].CreatedAt.Equal(retrieved[i-1].CreatedAt) { + if retrieved[i].Sequence < retrieved[i-1].Sequence { + t.Errorf("Messages with same created_at: message %d sequence (%d) < message %d sequence (%d)", + i, retrieved[i].Sequence, i-1, retrieved[i-1].Sequence) + } + } + } + + t.Logf("Successfully verified message ordering: created_at first, then sequence") + }) } // TestUpdateMessage tests updating messages diff --git a/data/bindata.go b/data/bindata.go index 64f8684c..d0520ac1 100644 --- a/data/bindata.go +++ b/data/bindata.go @@ -320,7 +320,7 @@ func cuiSetupIndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cui/setup/index.html", size: 10, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "cui/setup/index.html", size: 10, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -340,7 +340,7 @@ func cuiV09IndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cui/v0.9/index.html", size: 13, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "cui/v0.9/index.html", size: 13, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -360,7 +360,7 @@ func cuiV10IndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cui/v1.0/index.html", size: 49, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "cui/v1.0/index.html", size: 49, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -380,7 +380,7 @@ func cuiV10Layouts__indexAsyncJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cui/v1.0/layouts__index.async.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "cui/v1.0/layouts__index.async.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -400,7 +400,7 @@ func cuiV10UmiJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cui/v1.0/umi.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "cui/v1.0/umi.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -420,7 +420,7 @@ func initEnv() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.env", size: 219, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.env", size: 219, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -440,7 +440,7 @@ func initVscodeSettingsJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/settings.json", size: 4666, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/settings.json", size: 4666, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -460,7 +460,7 @@ func initVscodeTypesRuntimeConsoleDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/console.d.ts", size: 221, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/console.d.ts", size: 221, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -480,7 +480,7 @@ func initVscodeTypesRuntimeExceptionDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/exception.d.ts", size: 738, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/exception.d.ts", size: 738, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -500,7 +500,7 @@ func initVscodeTypesRuntimeFsDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/fs.d.ts", size: 8554, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/fs.d.ts", size: 8554, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -520,7 +520,7 @@ func initVscodeTypesRuntimeGlobalDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/global.d.ts", size: 1759, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/global.d.ts", size: 1759, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -540,7 +540,7 @@ func initVscodeTypesRuntimeHttpDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/http.d.ts", size: 6179, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/http.d.ts", size: 6179, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -560,7 +560,7 @@ func initVscodeTypesRuntimeIoDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/io.d.ts", size: 587, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/io.d.ts", size: 587, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -580,7 +580,7 @@ func initVscodeTypesRuntimeLogDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/log.d.ts", size: 1692, mode: os.FileMode(493), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/log.d.ts", size: 1692, mode: os.FileMode(493), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -600,7 +600,7 @@ func initVscodeTypesRuntimeNeoDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/neo.d.ts", size: 3750, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/neo.d.ts", size: 3750, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -620,7 +620,7 @@ func initVscodeTypesRuntimeProcessFsDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/process/fs.d.ts", size: 11133, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/process/fs.d.ts", size: 11133, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -640,7 +640,7 @@ func initVscodeTypesRuntimeProcessHttpDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/process/http.d.ts", size: 5653, mode: os.FileMode(493), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/process/http.d.ts", size: 5653, mode: os.FileMode(493), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -660,7 +660,7 @@ func initVscodeTypesRuntimeProcessModelDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/process/model.d.ts", size: 6656, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/process/model.d.ts", size: 6656, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -680,7 +680,7 @@ func initVscodeTypesRuntimeProcessDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/process.d.ts", size: 23165, mode: os.FileMode(493), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/process.d.ts", size: 23165, mode: os.FileMode(493), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -700,7 +700,7 @@ func initVscodeTypesRuntimeQueryDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/query.d.ts", size: 6124, mode: os.FileMode(493), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/query.d.ts", size: 6124, mode: os.FileMode(493), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -720,7 +720,7 @@ func initVscodeTypesRuntimeStoreDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/store.d.ts", size: 2251, mode: os.FileMode(493), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/store.d.ts", size: 2251, mode: os.FileMode(493), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -740,7 +740,7 @@ func initVscodeTypesRuntimeSuiDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/sui.d.ts", size: 1713, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/sui.d.ts", size: 1713, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -760,7 +760,7 @@ func initVscodeTypesRuntimeTimeDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime/time.d.ts", size: 711, mode: os.FileMode(493), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime/time.d.ts", size: 711, mode: os.FileMode(493), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -780,7 +780,7 @@ func initVscodeTypesRuntimeDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/runtime.d.ts", size: 424, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/runtime.d.ts", size: 424, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -800,7 +800,7 @@ func initVscodeTypesSuiDTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/.vscode/types/sui.d.ts", size: 8931, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/.vscode/types/sui.d.ts", size: 8931, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -820,7 +820,7 @@ func initAppYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/app.yao", size: 3115, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/app.yao", size: 3115, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -840,7 +840,7 @@ func initDataReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/README.md", size: 41, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/README.md", size: 41, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -860,7 +860,7 @@ func initDataTemplatesDefault__assetsReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/__assets/README.md", size: 33, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/__assets/README.md", size: 33, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -880,7 +880,7 @@ func initDataTemplatesDefault__assetsImagesIconsAppPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/__assets/images/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/__assets/images/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -900,7 +900,7 @@ func initDataTemplatesDefault__assetsImagesLogosLogo_colorSvg() (*asset, error) return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/__assets/images/logos/logo_color.svg", size: 2909, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/__assets/images/logos/logo_color.svg", size: 2909, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -920,7 +920,7 @@ func initDataTemplatesDefault__assetsImagesLogosWordmarkSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/__assets/images/logos/wordmark.svg", size: 3615, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/__assets/images/logos/wordmark.svg", size: 3615, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -940,7 +940,7 @@ func initDataTemplatesDefault__dataJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/__data.json", size: 30, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/__data.json", size: 30, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -960,7 +960,7 @@ func initDataTemplatesDefault__documentHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/__document.html", size: 492, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/__document.html", size: 492, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -980,7 +980,7 @@ func initDataTemplatesDefaultIndexIndexCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/index/index.css", size: 2896, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/index/index.css", size: 2896, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1000,7 +1000,7 @@ func initDataTemplatesDefaultIndexIndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/index/index.html", size: 2361, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/index/index.html", size: 2361, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1020,7 +1020,7 @@ func initDataTemplatesDefaultIndexIndexJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/data/templates/default/index/index.json", size: 31, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/data/templates/default/index/index.json", size: 31, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1040,7 +1040,7 @@ func initDbReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/db/README.md", size: 84, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/db/README.md", size: 84, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1060,7 +1060,7 @@ func initFlowsMenuFlowYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/flows/menu.flow.yao", size: 813, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/flows/menu.flow.yao", size: 813, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1080,7 +1080,7 @@ func initFormsAccountFormYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/forms/account.form.yao", size: 1194, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/forms/account.form.yao", size: 1194, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1100,7 +1100,7 @@ func initIconsAppIcns() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/icons/app.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/icons/app.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1120,7 +1120,7 @@ func initIconsAppIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/icons/app.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/icons/app.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1140,7 +1140,7 @@ func initIconsAppPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1160,7 +1160,7 @@ func initLoginsAdminLoginYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/logins/admin.login.yao", size: 302, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/logins/admin.login.yao", size: 302, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1180,7 +1180,7 @@ func initLogsReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/logs/README.md", size: 28, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/logs/README.md", size: 28, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1200,7 +1200,7 @@ func initModelsAdminUserModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/models/admin/user.mod.yao", size: 6416, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/models/admin/user.mod.yao", size: 6416, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1220,7 +1220,7 @@ func initModelsTestsPetModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/models/tests/pet.mod.yao", size: 525, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/models/tests/pet.mod.yao", size: 525, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1240,7 +1240,7 @@ func initNeoNeoYml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/neo/neo.yml", size: 724, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/neo/neo.yml", size: 724, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1260,7 +1260,7 @@ func initPublicReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/README.md", size: 108, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/README.md", size: 108, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1280,7 +1280,7 @@ func initPublicAssetsReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/assets/README.md", size: 33, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/assets/README.md", size: 33, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1300,7 +1300,7 @@ func initPublicAssetsImagesIconsAppPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/assets/images/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/assets/images/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1320,7 +1320,7 @@ func initPublicAssetsImagesLogosLogo_colorSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/assets/images/logos/logo_color.svg", size: 2909, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/assets/images/logos/logo_color.svg", size: 2909, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1340,7 +1340,7 @@ func initPublicAssetsImagesLogosWordmarkSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/assets/images/logos/wordmark.svg", size: 3615, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/assets/images/logos/wordmark.svg", size: 3615, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1360,7 +1360,7 @@ func initPublicAssetsLibsuiMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/assets/libsui.min.js", size: 12569, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/assets/libsui.min.js", size: 12569, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1380,7 +1380,7 @@ func initPublicAssetsLibsuiMinJsMap() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/assets/libsui.min.js.map", size: 38553, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/assets/libsui.min.js.map", size: 38553, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1400,7 +1400,7 @@ func initPublicIndexCfg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/index.cfg", size: 85, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/index.cfg", size: 85, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1420,7 +1420,7 @@ func initPublicIndexSui() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/public/index.sui", size: 5682, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/public/index.sui", size: 5682, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1440,7 +1440,7 @@ func initScriptsAccountTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/scripts/account.ts", size: 2521, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/scripts/account.ts", size: 2521, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1460,7 +1460,7 @@ func initScriptsAiNeoTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/scripts/ai/neo.ts", size: 375, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/scripts/ai/neo.ts", size: 375, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1480,7 +1480,7 @@ func initScriptsTestsTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/scripts/tests.ts", size: 1044, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/scripts/tests.ts", size: 1044, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1500,7 +1500,7 @@ func initScriptsUtilsTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/scripts/utils.ts", size: 1230, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/scripts/utils.ts", size: 1230, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1520,7 +1520,7 @@ func initSuisWebSuiYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/suis/web.sui.yao", size: 675, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/suis/web.sui.yao", size: 675, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1540,7 +1540,7 @@ func initTablesAccountTabYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/tables/account.tab.yao", size: 5597, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/tables/account.tab.yao", size: 5597, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1560,7 +1560,7 @@ func initTsconfigJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init/tsconfig.json", size: 178, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "init/tsconfig.json", size: 178, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1580,7 +1580,7 @@ func libsuiAgentTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "libsui/agent.ts", size: 15267, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "libsui/agent.ts", size: 15267, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1600,7 +1600,7 @@ func libsuiIndexTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "libsui/index.ts", size: 13049, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "libsui/index.ts", size: 13049, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1620,7 +1620,7 @@ func libsuiUtilsTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "libsui/utils.ts", size: 5959, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "libsui/utils.ts", size: 5959, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1640,7 +1640,7 @@ func libsuiYaoTs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "libsui/yao.ts", size: 4338, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "libsui/yao.ts", size: 4338, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1660,7 +1660,7 @@ func publicIndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "public/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "public/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1680,7 +1680,7 @@ func uiIndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "ui/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "ui/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1700,7 +1700,7 @@ func yaoDataIcons404Png() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1720,7 +1720,7 @@ func yaoDataIconsIconIcns() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1740,7 +1740,7 @@ func yaoDataIconsIconIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1760,7 +1760,7 @@ func yaoDataIconsIconPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1780,7 +1780,7 @@ func yaoDataIndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1800,7 +1800,7 @@ func yaoDataKbProvidersChunkingSemanticEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/chunking/semantic/en.json", size: 5543, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/chunking/semantic/en.json", size: 5543, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1820,7 +1820,7 @@ func yaoDataKbProvidersChunkingSemanticZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/chunking/semantic/zh-cn.json", size: 5446, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/chunking/semantic/zh-cn.json", size: 5446, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1840,7 +1840,7 @@ func yaoDataKbProvidersChunkingStructuredEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/chunking/structured/en.json", size: 2423, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/chunking/structured/en.json", size: 2423, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1860,7 +1860,7 @@ func yaoDataKbProvidersChunkingStructuredZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/chunking/structured/zh-cn.json", size: 2321, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/chunking/structured/zh-cn.json", size: 2321, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1880,7 +1880,7 @@ func yaoDataKbProvidersConverterMcpEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/mcp/en.json", size: 4235, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/mcp/en.json", size: 4235, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1900,7 +1900,7 @@ func yaoDataKbProvidersConverterMcpZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/mcp/zh-cn.json", size: 4060, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/mcp/zh-cn.json", size: 4060, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1920,7 +1920,7 @@ func yaoDataKbProvidersConverterOcrEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/ocr/en.json", size: 6631, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/ocr/en.json", size: 6631, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1940,7 +1940,7 @@ func yaoDataKbProvidersConverterOcrZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/ocr/zh-cn.json", size: 6501, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/ocr/zh-cn.json", size: 6501, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1960,7 +1960,7 @@ func yaoDataKbProvidersConverterOfficeEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/office/en.json", size: 5476, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/office/en.json", size: 5476, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1980,7 +1980,7 @@ func yaoDataKbProvidersConverterOfficeZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/office/zh-cn.json", size: 5356, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/office/zh-cn.json", size: 5356, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2000,7 +2000,7 @@ func yaoDataKbProvidersConverterUtf8EnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/utf8/en.json", size: 292, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/utf8/en.json", size: 292, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2020,7 +2020,7 @@ func yaoDataKbProvidersConverterUtf8ZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/utf8/zh-cn.json", size: 281, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/utf8/zh-cn.json", size: 281, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2040,7 +2040,7 @@ func yaoDataKbProvidersConverterVideoEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/video/en.json", size: 6411, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/video/en.json", size: 6411, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2060,7 +2060,7 @@ func yaoDataKbProvidersConverterVideoZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/video/zh-cn.json", size: 6297, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/video/zh-cn.json", size: 6297, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2080,7 +2080,7 @@ func yaoDataKbProvidersConverterVisionEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/vision/en.json", size: 4085, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/vision/en.json", size: 4085, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2100,7 +2100,7 @@ func yaoDataKbProvidersConverterVisionZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/vision/zh-cn.json", size: 3949, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/vision/zh-cn.json", size: 3949, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2120,7 +2120,7 @@ func yaoDataKbProvidersConverterWhisperEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/whisper/en.json", size: 4449, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/whisper/en.json", size: 4449, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2140,7 +2140,7 @@ func yaoDataKbProvidersConverterWhisperZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/converter/whisper/zh-cn.json", size: 4312, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/converter/whisper/zh-cn.json", size: 4312, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2160,7 +2160,7 @@ func yaoDataKbProvidersEmbeddingFastembedEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/embedding/fastembed/en.json", size: 6865, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/embedding/fastembed/en.json", size: 6865, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2180,7 +2180,7 @@ func yaoDataKbProvidersEmbeddingFastembedZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/embedding/fastembed/zh-cn.json", size: 6685, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/embedding/fastembed/zh-cn.json", size: 6685, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2200,7 +2200,7 @@ func yaoDataKbProvidersEmbeddingOpenaiEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/embedding/openai/en.json", size: 5636, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/embedding/openai/en.json", size: 5636, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2220,7 +2220,7 @@ func yaoDataKbProvidersEmbeddingOpenaiZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/embedding/openai/zh-cn.json", size: 5463, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/embedding/openai/zh-cn.json", size: 5463, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2240,7 +2240,7 @@ func yaoDataKbProvidersExtractionOpenaiEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/extraction/openai/en.json", size: 9110, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/extraction/openai/en.json", size: 9110, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2260,7 +2260,7 @@ func yaoDataKbProvidersExtractionOpenaiZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/extraction/openai/zh-cn.json", size: 8827, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/extraction/openai/zh-cn.json", size: 8827, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2280,7 +2280,7 @@ func yaoDataKbProvidersFetcherHttpEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/http/en.json", size: 5885, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/http/en.json", size: 5885, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2300,7 +2300,7 @@ func yaoDataKbProvidersFetcherHttpZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/http/zh-cn.json", size: 5925, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/http/zh-cn.json", size: 5925, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2320,7 +2320,7 @@ func yaoDataKbProvidersFetcherMcpEnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/mcp/en.json", size: 6819, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/mcp/en.json", size: 6819, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2340,7 +2340,7 @@ func yaoDataKbProvidersFetcherMcpZhCnJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/mcp/zh-cn.json", size: 6611, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/mcp/zh-cn.json", size: 6611, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2360,7 +2360,7 @@ func yaoFieldsModelTransJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/fields/model.trans.json", size: 14938, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/fields/model.trans.json", size: 14938, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2380,7 +2380,7 @@ func yaoLangsEnUsJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2400,7 +2400,7 @@ func yaoLangsZhCnGlobalYml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/langs/zh-cn/global.yml", size: 1762, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/langs/zh-cn/global.yml", size: 1762, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2420,7 +2420,7 @@ func yaoLangsZhCnLoginsAdminLoginYml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/langs/zh-cn/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/langs/zh-cn/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2440,7 +2440,7 @@ func yaoLangsZhCnLoginsUserLoginYml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/langs/zh-cn/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/langs/zh-cn/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2460,7 +2460,7 @@ func yaoLangsZhHkGlobalYml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/langs/zh-hk/global.yml", size: 1762, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/langs/zh-hk/global.yml", size: 1762, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2480,7 +2480,7 @@ func yaoLangsZhHkLoginsAdminLoginYml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/langs/zh-hk/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/langs/zh-hk/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2500,7 +2500,7 @@ func yaoLangsZhHkLoginsUserLoginYml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/langs/zh-hk/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/langs/zh-hk/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2520,12 +2520,12 @@ func yaoModelsAgentAssistantModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/agent/assistant.mod.yao", size: 6758, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/agent/assistant.mod.yao", size: 6758, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _yaoModelsAgentChatModYao = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x96\xcd\x8e\x1b\x37\x0c\xc7\xef\x7e\x0a\x42\xa7\x14\xd8\x06\x41\xd1\x14\x58\xdf\x16\xc9\x25\x40\x17\x2d\xd0\x14\x3d\x04\x81\x41\x8f\x68\x5b\xad\x3e\xa6\x22\x67\x51\x63\xb1\xef\x5e\x48\x9e\x19\x6b\x3c\xf2\xae\x9d\xec\x65\x0e\x14\x87\xfa\xff\x48\x89\xe2\xe3\x02\x40\x79\x74\xa4\x96\xa0\x3e\xec\x50\xd4\x4d\xb2\x58\x5c\x93\x9d\x9a\x34\x71\x13\x4d\x2b\x26\xf8\x61\x01\x98\x98\x4d\xf0\x20\xb8\xb6\x04\x9b\x10\x81\x25\x44\xe3\xb7\xd0\xa4\x65\x47\x82\x1a\x05\x01\xbd\x1e\x7d\x8d\xdf\x84\xe8\x30\xc7\xc9\x81\x05\xb7\xac\x96\xf0\x45\xe1\x96\xbc\xa8\x1b\x50\xbc\x67\x21\xa7\xbe\xe6\xe5\x75\x67\xac\x98\xb4\xa7\xc4\x8e\xb2\x29\x12\xea\xe0\xed\xbe\xb4\x71\x88\xa2\x96\x70\x7b\x7b\x7b\xdb\x47\x5d\xdb\x04\xf5\x78\xc4\xcb\xf1\x57\x4d\x26\x02\xd5\x04\xe7\xd2\x7e\x4b\x50\x77\x69\xe1\x20\x79\x42\xa4\xe0\x29\xc7\x6a\x82\xed\x9c\xcf\x22\x17\x00\x00\x8f\xf9\x5b\x24\xce\xe8\x8c\x92\x6d\xb2\x6f\xb3\xed\xd3\xc7\xa3\x6d\x4c\x67\x69\x2c\x05\x74\x12\x7e\x34\xbe\x89\x94\x2c\xd0\x46\xe3\x30\xee\xe1\x1f\xda\xab\xec\xfd\x74\x53\xdf\x37\x49\x5e\xd5\x36\x67\x49\x55\xa8\x08\xc8\x65\x3b\xa3\xe2\x4f\x6f\xfe\xed\xe8\x90\x07\xa3\xc9\x8b\xd9\x18\x8a\x45\x10\xf2\x5b\xd9\xa9\x25\xfc\xf2\xf3\x68\xf3\x9d\xb5\x7d\xa6\x37\x68\x99\xc6\x85\x2e\x07\xeb\x2b\xf4\x2c\x84\x18\xb1\x74\x05\xc2\xe7\xa9\x7f\x01\x90\xe1\x4e\xc2\x8d\xa2\xdf\xbf\x7b\x57\x53\xfd\xa2\x3c\x64\x36\x2c\xe8\xaf\x4c\xf4\xdd\xf0\xdb\xb9\x6c\xdf\x31\x87\xc6\xa0\x90\x06\xac\xfa\x8e\xca\x7f\xaa\x2b\x9f\xe6\xdb\x78\x4d\xff\x5d\xc2\x63\x91\x65\xd5\x04\xef\xa9\x91\x10\xaf\x20\xfa\x15\x59\xe0\xc3\xfc\xc7\x82\x29\xbb\x74\x4c\x1a\xc6\x0d\xe0\xd3\x47\x78\xd3\xb5\x3a\x83\x06\x0f\x84\xcd\x0e\x1c\x31\xe3\x96\x7e\xb8\x1c\x76\xb8\xe7\xd7\xb1\xba\xa0\xaf\x39\x59\xf7\x13\xf7\xd3\x83\x95\x82\xc1\x1b\x4d\x1b\xec\xac\x2c\xf3\x35\xa9\x01\xbc\xbf\xa0\x58\x7d\x90\xe1\x0a\x3f\x7f\xc9\x59\x50\x3a\x9e\x63\x90\xef\x5c\x05\xe2\x8f\x13\xf7\x53\x8c\xd3\x70\x61\x68\xe9\x5f\x14\x36\x62\x1e\x28\x35\x47\x8c\xcd\xce\x3c\x90\x3e\xf4\xe0\x53\xcd\x83\xdf\xeb\x1d\xca\xb6\x5b\x5b\xd3\xcc\x19\xd7\x21\x58\x42\x5f\xc1\xfc\xfd\xe4\x8f\x02\xf3\xaf\x1d\xc9\x8e\x22\xf0\x0e\x63\xba\x5d\x4d\x0c\xcc\x80\xd6\x82\x10\xba\x02\xfd\x88\x34\x95\x7d\xca\xf3\x7c\x79\xd2\x2e\x97\x57\x67\xea\x5d\xa8\x4e\x2b\xe9\xe5\xe4\x26\xb4\x54\x2d\x4f\x1b\xcd\x03\x4a\xae\x4f\x02\xa9\xd7\x66\x74\x7a\xbd\xe2\xe4\xa7\x75\x06\x68\xbc\xd0\x76\xf2\x3c\x8c\x8c\x13\xff\x12\x31\x44\x81\x10\x35\xc5\x3c\x2b\x68\xc3\xad\xc5\x7d\xad\x1e\xe9\x19\x7f\xb9\x8b\xf5\x6d\x64\x85\x15\x79\xa9\xe1\x88\x71\x74\xae\x91\xdd\x1f\xfe\x85\xbb\xba\xd4\xcf\xc6\x11\x0b\xba\x16\xc2\x06\xd2\x66\x43\xcf\xaa\x26\xf6\x1b\xbb\x53\x3f\x1e\xcd\xc5\xff\xcd\xa1\x76\xe6\xef\x67\x3f\x94\xef\x89\xd6\x26\x1d\x15\xb4\x30\x0f\x5c\x7d\xf0\x16\x00\x5f\xfb\x79\xca\xe6\x79\x2c\x4d\x38\x07\x95\xc7\x57\x6f\x34\x15\xf2\x76\xc8\xbf\xf9\x22\x13\xa9\x33\x66\x81\xab\xd5\x1e\xc3\xdb\x3c\x67\xbd\x3d\x46\x18\xfd\xd2\x3c\x73\xf6\x45\xdd\x84\x48\x66\xeb\x67\x0e\x65\x0a\x55\x5f\x04\x3e\xa3\xea\x1e\xfd\xfe\x05\x59\xb3\x32\xf6\xa2\x66\xa3\x54\xa1\x67\x58\x9b\x48\x89\xc4\x9d\xfb\x1e\x25\x87\x00\xdf\x21\x64\xd1\x8b\x39\xf6\x88\xc7\x34\x4d\xf5\x07\x97\x87\x73\x99\x2e\xf0\x46\x56\x9a\x2c\x09\x15\xd6\x96\xa2\x33\x79\xda\xed\x6d\xf0\xb4\x78\x5a\xfc\x1f\x00\x00\xff\xff\xf0\x08\x02\x91\x11\x0c\x00\x00") +var _yaoModelsAgentChatModYao = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x96\xcd\x8e\x1b\x37\x0c\xc7\xef\x7e\x0a\x42\xa7\x16\xd8\x06\x41\xd1\x14\x58\xdf\x16\xc9\x25\x40\x17\x2d\xd0\x14\x3d\x04\x81\x41\x8f\x68\x5b\xad\x3e\xa6\x22\x67\xd1\xc1\x62\xdf\x3d\x90\x3c\x33\xd6\x78\xe4\x64\xbd\xc9\x65\x0e\x14\x87\xfa\xff\x48\x51\xe2\xe3\x0a\x40\x79\x74\xa4\xd6\xa0\xde\x1e\x50\xd4\x4d\xb2\x58\xdc\x92\x9d\x9b\x34\x71\x13\x4d\x2b\x26\xf8\x71\x01\x98\x98\x4d\xf0\x20\xb8\xb5\x04\xbb\x10\x81\x25\x44\xe3\xf7\xd0\xa4\x65\x47\x82\x1a\x05\x01\xbd\x9e\x7c\x8d\xdf\x85\xe8\x30\xc7\xc9\x81\x05\xf7\xac\xd6\xf0\x51\xe1\x9e\xbc\xa8\x1b\x50\xdc\xb3\x90\x53\x9f\xf2\xf2\xb6\x33\x56\x4c\xda\x53\x62\x47\xd9\x14\x09\x75\xf0\xb6\x2f\x6d\x1c\xa2\xa8\x35\xdc\xde\xde\xde\x0e\x51\xb7\x36\x41\x3d\x9e\xf0\x72\xfc\x4d\x93\x89\x40\x35\xc1\xb9\xb4\xdf\x1a\xd4\x5d\x5a\x38\x4a\x9e\x11\x29\x78\xca\xb1\x9a\x60\x3b\xe7\xb3\xc8\x15\x00\xc0\x63\xfe\x16\x89\x33\x3a\xa3\x64\x9b\xf4\x6d\xb6\xbd\x7f\x77\xb2\x4d\xe9\x2c\x8d\xa5\x80\x4e\xc2\x4f\xc6\x37\x91\x92\x05\xda\x68\x1c\xc6\x1e\xfe\xa5\x5e\x65\xef\xa7\x9b\xfa\xbe\x49\xf2\xa6\xb6\x39\x4b\xaa\x42\x45\x40\x2e\xdb\x05\x15\x7f\x79\xf3\x5f\x47\xc7\x3c\x18\x4d\x5e\xcc\xce\x50\x2c\x82\x90\xdf\xcb\x41\xad\xe1\xd7\x5f\x26\x9b\xef\xac\x1d\x32\xbd\x43\xcb\x34\x2d\x74\x39\xd8\x50\xa1\x2f\x42\x88\x11\x4b\x57\x20\x7c\x98\xfb\x17\x00\x19\xee\x2c\xdc\x24\xfa\xcd\xeb\xd7\x35\xd5\x5f\x95\x87\xcc\x86\x05\xfd\x95\x89\xbe\x1b\x7f\xbb\x94\xed\x3b\xe6\xd0\x18\x14\xd2\x80\x55\xdf\x49\xf9\xcf\x75\xe5\xf3\x7c\x1b\xaf\xe9\xff\xe7\xf0\x58\x64\xd9\x34\xc1\x7b\x6a\x24\xc4\x2b\x88\x7e\x43\x16\x78\xbb\xfc\xb1\x60\xca\x2e\x1d\x93\x86\x69\x03\x78\xff\x0e\x7e\xe8\x5a\x9d\x41\x83\x07\xc2\xe6\x00\x8e\x98\x71\x4f\x3f\x3e\x1f\x76\xec\xf3\x17\xb0\xba\xa0\xaf\x39\x5e\x99\xe1\x7e\xf6\x4f\x9d\x30\xdf\x70\x41\xd3\x55\x78\x6f\x5e\x76\x08\x59\x50\x3a\x5e\x52\x90\xef\x5c\x85\xe1\xcf\x33\xf7\xf3\x1e\x39\x0f\x17\xc6\x6b\xfd\xa3\xc2\x46\xcc\x03\xa5\x0b\x12\x63\x73\x30\x0f\xa4\x8f\xf7\x70\xf6\xd3\xb4\xc3\xce\xe6\x38\xa3\xdf\xf7\x3b\x98\x6d\xb7\xb5\xa6\x59\x32\x6e\x43\xb0\x84\xbe\x82\xf9\xc7\xd9\x1f\x05\xe6\xdf\x07\x92\x03\x45\xe0\x03\xc6\xd4\x61\x4d\x0c\xcc\x80\xd6\x82\x10\xba\x02\xfd\x84\x34\x97\x7d\xce\xf3\xe5\xf2\xa4\x5d\x9e\x5f\x9d\xb9\x77\xa1\x3a\xad\xa4\xd7\x93\x9b\xd0\x52\xb5\x3c\x6d\x34\x0f\x28\xb9\x3e\x09\xa4\x5e\x9b\xc9\xe9\xfb\x15\x27\x3f\xaf\x0b\x40\xe3\x85\xf6\xb3\x27\x62\x62\x9c\xf9\x97\x88\x21\x0a\x84\xa8\x29\xe6\x79\x41\x1b\x6e\x2d\xf6\xb5\x7a\xa4\xa7\xfc\x19\xdd\x7d\xec\xb5\x0d\x56\xe4\xa5\xae\x14\xe3\xe8\x62\x97\x1f\xff\x85\xbb\xba\xd4\x0f\xc6\x11\x0b\xba\x16\xc2\x0e\xd2\x66\x63\x63\x57\x13\xfb\xb2\x1b\x6a\x1c\x91\x96\xe2\xff\xe1\x50\x3b\xf3\xf7\x8b\x1f\xca\x37\x45\x6b\x93\x8e\x0a\x5a\x58\x06\xae\xde\x37\x2b\x80\x4f\xc3\x4c\x65\xf3\x4c\x96\xa6\x9c\xa3\xca\xd3\xcb\x37\x99\x0a\x79\x07\xe4\xdf\x7d\x91\x89\x74\x13\x66\x81\x9b\x4d\x8f\xe1\x55\x9e\xb5\x5e\x9d\x22\x4c\x7e\x69\xa6\xb9\xf8\xaa\xee\x42\x24\xb3\xf7\x0b\x87\x32\x85\x6a\x28\x02\x5f\x50\x75\x8f\xbe\xff\x8a\xac\x45\x19\x07\x51\x8b\x71\xaa\xd0\x33\xae\xcd\xa4\x44\xe2\xce\x7d\x8b\x92\x63\x80\x6f\x10\xb2\x1a\xc4\x9c\xee\x88\xc7\x34\x51\x0d\x07\x97\xc7\x73\x99\x1a\x78\x27\x1b\x4d\x96\x84\x0a\x6b\x4b\xd1\x99\x3c\xf1\x0e\x36\x78\x5a\x3d\xad\x3e\x07\x00\x00\xff\xff\x1f\x9b\x6e\x70\x15\x0c\x00\x00") func yaoModelsAgentChatModYaoBytes() ([]byte, error) { return bindataRead( @@ -2540,12 +2540,12 @@ func yaoModelsAgentChatModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/agent/chat.mod.yao", size: 3089, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/agent/chat.mod.yao", size: 3093, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _yaoModelsAgentMessageModYao = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x57\x4d\x6f\xc3\x36\x0c\xbd\xe7\x57\x10\x3a\x65\x80\xdb\x15\xc3\x36\x20\xb9\x75\xdb\xa5\x87\x62\xc5\xd6\x9d\x8a\xc2\x50\x6c\xc6\x51\xab\x8f\x54\xa2\xbb\x06\x41\xfe\xfb\x20\xf9\x23\x72\xad\x04\x75\xb0\x5e\x0a\x94\x94\xe8\xf7\x48\x3e\x8a\xd9\xcf\x00\x98\xe6\x0a\xd9\x12\xd8\x3d\x3a\xc7\x2b\x64\x99\x37\x4a\xbe\x42\x39\xb2\x96\xe8\x0a\x2b\xb6\x24\x8c\xf6\xbe\xdf\x37\x9c\x40\x35\x07\x80\xf8\x4a\x22\xac\x8d\x05\x47\xc6\x0a\x5d\x41\xed\xd0\x5e\xbd\x0b\x27\xbc\xa3\x3d\xe6\x9a\x40\xc4\x2b\xc7\x96\xf0\xc4\x78\x85\x9a\x58\x06\xcc\xed\x1c\xa1\x62\xcf\xc1\xbd\xaa\x85\x24\xe1\xbf\x41\xb6\xc6\x60\xb2\xc8\x4b\xa3\xe5\x2e\xb6\x39\x63\x89\x2d\x61\xb1\x58\x2c\xda\xa8\x2b\xe9\xa9\xec\x8f\xa4\x42\xfc\x5c\x75\x24\x80\x15\x46\x29\xff\xc9\x25\xb0\x5b\xef\x83\x62\x44\x82\xc1\x21\x84\x2b\x8c\xac\x95\x0e\x38\x67\x00\x00\xfb\xf0\x37\xca\x98\x28\x03\x9b\x60\xa3\xdd\x36\xd8\xee\xfe\x38\xda\xfa\x24\xc6\xc6\x18\x40\x4d\xe6\x4a\xe8\xc2\xa2\xb7\xc0\xd6\x0a\xc5\xed\x0e\x5e\x71\xc7\xc2\xe9\x43\x96\xfe\x6e\x8b\x36\x4f\x7d\xdf\x91\xcf\x7d\x02\x43\x5b\x48\x38\x81\xa5\x73\x8b\x12\x35\x89\xb5\x40\x0b\xf3\x5a\x8b\xb7\x1a\xe1\x5f\x41\x1b\xa1\xc1\xe2\x5b\x8d\x8e\x7e\x88\x62\xa3\xae\x68\xc3\x96\xf0\xeb\xcf\xbd\x4d\xd7\x52\xb6\x65\x58\x73\xe9\xf0\x2c\x11\x9f\xfb\x69\x2c\x42\xcb\x9d\xa0\xf0\xc0\x6d\x5f\xd0\x41\x19\xbe\x00\xb3\x77\x08\x5d\xe2\x47\xdb\x64\x67\xb1\xb7\xe9\x98\x06\xff\xaf\xe6\xd2\x29\x06\x47\x77\x10\x52\x65\x4d\xbd\x1d\x06\x3a\x4f\xa5\x53\xc6\x44\x26\x46\xe2\x98\x03\xea\x5a\xa5\x18\x0c\x0e\x27\x1a\x68\x18\xcd\x74\xc3\xe2\x89\xf9\x71\xe0\x15\xc8\x9d\x13\x8e\xb8\xa6\x46\xec\xff\x53\x39\x02\xec\xaf\x17\xe2\x71\x70\x3c\x41\xc3\x47\x80\x39\xe1\x07\x65\x20\x14\xaf\x30\x03\x69\x78\x29\x74\x95\x01\x19\x23\xf3\x82\x4b\x99\x81\x45\xb2\x02\xdf\xb9\xcc\x00\xa9\xb8\x4e\x89\xe3\x97\x9b\xcb\xc4\xb1\xb5\x66\xeb\xc6\x94\x5e\x9c\xd1\x09\x42\x0f\xc3\xd3\x09\x46\x3e\x1e\x5a\x12\xe8\x60\x5e\x18\x4d\xa8\x29\x83\xda\x8e\x91\x4f\x42\xb9\x92\xa6\x78\x9d\x26\x82\xdf\xfc\x95\x53\x12\x68\x9c\x5d\xe7\x4f\xd1\xf1\x65\xcd\x4f\x1b\xff\xb2\x4c\x23\xf0\x18\xee\x9c\x62\xd0\x7a\x23\x0a\x41\xcc\x85\xd1\x45\x6d\xc3\x84\xf2\x75\xe0\x5e\x17\xee\x9b\xc9\xf5\x52\x9b\xc6\xef\xb6\xbb\x76\x8a\x62\x7c\x00\xe6\x2f\x46\x68\x20\x03\x15\x12\xf8\x2f\xff\xc8\xdf\x39\x71\x9b\xd2\xc2\x4f\x37\x49\x31\x5c\xc6\xae\x30\x5a\x63\x41\xc6\x4e\x79\x3f\xc6\x77\x22\x5e\xbd\xd7\xf3\xaa\x1d\x96\xa1\x72\xb4\x11\x0e\x54\xb4\x07\x7d\x23\x27\xe7\x5f\x00\x5d\x24\x46\x99\xd0\x84\x15\xda\x04\xa7\xbf\x47\x77\x12\xea\x37\xb6\x44\xdb\x3d\xe5\xfe\x89\xbc\x50\xef\x0a\x89\x97\x9c\xf8\x97\x07\xd3\xfd\xe8\x42\xdc\x48\x65\x29\xbc\x10\xb8\x84\x2e\x30\xcc\xfb\xf1\x9a\x8b\xb2\x1d\xb6\xfe\xeb\xe7\xe6\xd4\x31\xaf\x33\x80\xe7\x76\x61\x94\xad\xc6\x96\x2d\x8b\xb0\x6e\xf4\xff\x45\xc8\x37\xdc\xfd\xa9\xa3\xf4\x29\x53\x36\xd8\xf3\x7c\xc7\xcd\x75\xd8\x21\xaf\x87\x39\xf3\x3b\x5a\x6a\x81\x59\x1b\x8b\xa2\xd2\xb1\x2f\x4e\x67\xf4\xf8\x5d\x8a\xe3\x18\xe1\x33\x98\xb4\xda\x23\x44\x83\x03\x7d\xba\x9a\x65\x37\x74\x28\x9e\x5d\x76\x3f\x72\xe5\xaa\x3c\xd0\x72\xf8\x16\xd7\xb3\xdf\x93\x8f\x09\x89\x5a\xf9\x39\xd1\xcb\x5e\x0e\xa9\x86\xb8\xf3\x9e\xa0\x3a\x15\x37\xae\x9f\xa3\x71\xef\x9e\x6d\xd1\x0e\x69\xb7\xa1\x8d\xa4\x1b\x03\x8e\xd7\xb8\xc1\x66\x3d\x46\xdd\xac\xc3\x49\xd8\xff\x34\x9b\x72\x61\xb4\x23\xcb\x85\xa6\x98\x42\x2e\xca\x4f\x3b\x34\xfb\xd4\xab\xfd\x96\xb4\x07\x46\x42\xa1\x23\xae\xb6\xae\x1b\x22\xfe\x87\xce\x9a\xf2\x12\x25\x12\x76\x56\x38\xcc\x0e\xb3\xff\x02\x00\x00\xff\xff\x58\xd0\xed\xdc\xc0\x0d\x00\x00") +var _yaoModelsAgentMessageModYao = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x57\x4d\x8f\xdb\x36\x10\xbd\xfb\x57\x0c\x78\x72\x01\x65\x1b\x14\x6d\x81\xf5\x2d\x6d\x2f\x39\x2c\x1a\xb4\xe9\x29\x58\x08\xb4\x38\x96\x99\xe5\x87\x97\x1c\x6d\xd7\x30\xfc\xdf\x0b\x52\x1f\xa6\x56\xb4\x6b\x19\xc9\xc5\x80\x67\xc8\xe1\x7b\xc3\x79\xc3\xd1\x61\x01\xc0\x0c\xd7\xc8\x56\xc0\x1e\xd0\x7b\x5e\x23\x2b\x82\x51\xf1\x35\xaa\x89\x55\xa0\xaf\x9c\xdc\x91\xb4\x26\xf8\x7e\xdf\x72\x02\xdd\x2e\x00\xe2\x6b\x85\xb0\xb1\x0e\x3c\x59\x27\x4d\x0d\x8d\x47\xf7\xee\x45\x7a\x19\x1c\xdd\x32\xdf\x06\x22\x5e\x7b\xb6\x82\x2f\x8c\xd7\x68\x88\x15\xc0\xfc\xde\x13\x6a\xf6\x18\xdd\xeb\x46\x2a\x92\xe1\x0c\x72\x0d\x46\x93\x43\x2e\xac\x51\xfb\xd4\xe6\xad\x23\xb6\x82\xfb\xfb\xfb\xfb\x2e\xea\x5a\x05\x2a\x87\x13\xa9\x18\xbf\xd4\x3d\x09\x60\x95\xd5\x3a\x1c\xb9\x02\xf6\x21\xf8\xa0\x9a\x90\x60\x70\x8c\xe1\x2a\xab\x1a\x6d\x22\xce\x05\x00\xc0\x21\xfe\x26\x19\x93\x22\xb2\x89\x36\xda\xef\xa2\xed\xe3\x1f\x27\xdb\x90\xc4\xd4\x98\x02\x68\xc8\xbe\x93\xa6\x72\x18\x2c\xb0\x73\x52\x73\xb7\x87\x27\xdc\xb3\xb8\xfa\x58\xe4\xcf\xed\xd0\x96\xb9\xf3\x3d\x85\xdc\x67\x30\x74\x17\x09\x67\xb0\xf4\x6e\x29\xd0\x90\xdc\x48\x74\xb0\x6c\x8c\x7c\x6e\x10\xfe\x95\xb4\x95\x06\x1c\x3e\x37\xe8\xe9\x87\x24\x36\x9a\x9a\xb6\x6c\x05\xbf\xfe\x3c\xd8\x4c\xa3\x54\x77\x0d\x1b\xae\x3c\x5e\x24\x12\x72\x3f\x8f\x45\x2c\xb9\x33\x14\x3e\x71\x37\x5c\xe8\xe8\x1a\xae\x80\x39\x38\xa4\x11\xf8\xda\x15\xd9\x45\xec\x5d\x3a\xe6\xc1\xff\xab\xdd\x74\x8e\xc1\xc9\x1d\x85\x54\x3b\xdb\xec\xc6\x81\x2e\x53\xe9\x95\x31\x93\x89\x55\x38\xe5\x80\xa6\xd1\x39\x06\xa3\xc5\x99\x02\x1a\x47\xb3\x7d\xb3\xf8\xc2\x42\x3b\x08\x0a\xe4\xde\x4b\x4f\xdc\x50\x2b\xf6\x6f\x74\x1d\x11\xf6\xf5\x17\xf1\x79\xb4\x3c\x43\x23\x44\x80\x25\xe1\x2b\x15\x20\x35\xaf\xb1\x00\x65\xb9\x90\xa6\x2e\x80\xac\x55\x65\xc5\x95\x2a\xc0\x21\x39\x89\x2f\x5c\x15\x80\x54\xdd\xe5\xc4\xf1\xcb\xfb\xdb\xc4\xb1\x73\x76\xe7\xa7\x94\xbe\x7a\x6b\x32\x84\x3e\x8d\x57\x67\x18\x85\x78\xe8\x48\xa2\x87\x65\x65\x0d\xa1\xa1\x02\x1a\x37\x45\x3e\x0b\xe5\x5a\xd9\xea\x69\x9e\x08\x7e\x0b\x5b\xce\x49\xa0\x75\xf6\x95\x3f\x47\xc7\xb7\x15\x3f\x6d\xc3\xcb\x32\x8f\xc0\xe7\xb8\xe7\x1c\x83\xce\x9b\x50\x88\x62\xae\xac\xa9\x1a\x17\x3b\x54\xb8\x07\x1e\x74\xe1\xbf\x33\xb9\x41\x6a\xf3\xf8\x7d\xe8\xb7\x9d\xa3\x98\x2e\x80\xe5\x57\x2b\x0d\x90\x85\x1a\x09\xc2\xc9\x3f\xf2\x17\x4e\xdc\xe5\xb4\xf0\xd3\xfb\xac\x18\x6e\x63\x57\x59\x63\xb0\x22\xeb\xe6\xbc\x1f\xd3\x3d\x09\xaf\xc1\x1b\x78\x35\x1e\x45\xbc\x39\xda\x4a\x0f\x3a\x99\x83\xbe\x23\x27\x6d\xc5\x9c\x36\xf6\x30\x5a\x9e\x32\x89\x53\x8d\x15\x98\xa7\x01\xcb\xf8\x4a\x06\x2b\xf7\x4f\xd7\x77\xad\xff\xc5\xef\xc3\x0b\x66\xaa\x0c\x07\x69\x08\x6b\x74\x19\x12\x7f\x4f\xf6\x64\xba\x97\x75\x02\x5d\x3f\x8a\x04\xf0\x37\xf6\x2b\x8d\xc4\x05\x27\x7e\x75\x63\x7d\x98\x6c\x48\x85\x20\x84\x0c\x42\xe6\x0a\xfa\xc0\xb0\x1c\x9e\x87\x52\x8a\xee\xb1\x08\xa7\x5f\xea\xb3\xa7\xbc\x2e\x00\x1e\xbb\x81\x57\x75\x3d\x62\xd5\xb1\x88\xe3\xd2\xf0\x2f\x41\xbe\xe5\xfe\x4f\x93\xa4\x2f\xdc\x7b\xc4\x5e\x96\x7b\x6e\xef\xe2\x0c\x7c\x37\xce\x59\x98\x31\x73\x03\xd8\xc6\x3a\x94\xb5\x49\x7d\x69\x3a\x93\xc7\xfb\x56\x1c\xa7\x08\x6f\xc1\xe4\xbb\x55\x82\x68\xb4\x60\x48\x57\x3b\xac\x47\x85\xe1\xc5\x61\xfd\xb5\xd4\xbe\x2e\x23\x2d\x8f\xcf\xe9\x7d\x0e\x73\xfe\x29\x21\x49\x29\x3f\x66\x6a\x39\xc8\x39\x57\x10\x1f\x83\x27\xca\x4d\xa7\x85\x1b\xde\x81\xb4\x76\x2f\x96\x68\x8f\xb4\x9f\x30\x27\xad\x27\x05\x9c\x8e\xa1\xa3\x2f\x83\x29\xea\x76\x9c\xcf\xc2\xfe\xa7\x9d\xf4\x2b\x6b\x3c\x39\x2e\x0d\xa5\x14\x4a\x29\xde\x7c\x03\xb0\x37\xb5\x3a\x4c\x79\x07\x60\x24\x35\x7a\xe2\x7a\xe7\xfb\x26\x18\x3e\xd4\x36\x54\x0a\x54\x48\xd8\x5b\xe1\xb8\x38\x2e\xfe\x0b\x00\x00\xff\xff\x6d\x86\xdb\x48\x80\x0e\x00\x00") func yaoModelsAgentMessageModYaoBytes() ([]byte, error) { return bindataRead( @@ -2560,7 +2560,7 @@ func yaoModelsAgentMessageModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/agent/message.mod.yao", size: 3520, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/agent/message.mod.yao", size: 3712, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2580,7 +2580,7 @@ func yaoModelsAgentResumeModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/agent/resume.mod.yao", size: 3896, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/agent/resume.mod.yao", size: 3896, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2600,7 +2600,7 @@ func yaoModelsAttachmentModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/attachment.mod.yao", size: 4687, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/attachment.mod.yao", size: 4687, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2620,7 +2620,7 @@ func yaoModelsAuditModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/audit.mod.yao", size: 5588, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/audit.mod.yao", size: 5588, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2640,7 +2640,7 @@ func yaoModelsConfigModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/config.mod.yao", size: 1649, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/config.mod.yao", size: 1649, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2660,7 +2660,7 @@ func yaoModelsDslModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/dsl.mod.yao", size: 3826, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/dsl.mod.yao", size: 3826, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2680,7 +2680,7 @@ func yaoModelsInvitationModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/invitation.mod.yao", size: 6693, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/invitation.mod.yao", size: 6693, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2700,7 +2700,7 @@ func yaoModelsJobCategoryModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/job/category.mod.yao", size: 2041, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/job/category.mod.yao", size: 2041, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2720,7 +2720,7 @@ func yaoModelsJobExecutionModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/job/execution.mod.yao", size: 7201, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/job/execution.mod.yao", size: 7201, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2740,7 +2740,7 @@ func yaoModelsJobJobModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/job/job.mod.yao", size: 6330, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/job/job.mod.yao", size: 6330, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2760,7 +2760,7 @@ func yaoModelsJobLogModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/job/log.mod.yao", size: 4711, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/job/log.mod.yao", size: 4711, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2780,7 +2780,7 @@ func yaoModelsKbCollectionModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/kb/collection.mod.yao", size: 5390, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/kb/collection.mod.yao", size: 5390, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2800,7 +2800,7 @@ func yaoModelsKbDocumentModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/kb/document.mod.yao", size: 9906, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/kb/document.mod.yao", size: 9906, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2820,7 +2820,7 @@ func yaoModelsMemberModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/member.mod.yao", size: 14798, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/member.mod.yao", size: 14798, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2840,7 +2840,7 @@ func yaoModelsRoleModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/role.mod.yao", size: 6434, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/role.mod.yao", size: 6434, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2860,7 +2860,7 @@ func yaoModelsTeamModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/team.mod.yao", size: 15823, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/team.mod.yao", size: 15823, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2880,7 +2880,7 @@ func yaoModelsUserOauth_accountModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/user/oauth_account.mod.yao", size: 6928, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/user/oauth_account.mod.yao", size: 6928, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2900,7 +2900,7 @@ func yaoModelsUserTypeModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/user/type.mod.yao", size: 7502, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/user/type.mod.yao", size: 7502, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2920,7 +2920,7 @@ func yaoModelsUserModYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/models/user.mod.yao", size: 12335, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/models/user.mod.yao", size: 12335, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2940,7 +2940,7 @@ func yaoReleaseAppYaz() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/release/app.yaz", size: 181682, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/release/app.yaz", size: 181682, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2960,7 +2960,7 @@ func yaoStoresAgentCacheLruYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/agent/cache.lru.yao", size: 301, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/agent/cache.lru.yao", size: 301, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -2980,7 +2980,7 @@ func yaoStoresAgentMemoryBadgerYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/agent/memory.badger.yao", size: 352, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/agent/memory.badger.yao", size: 352, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -3000,7 +3000,7 @@ func yaoStoresCacheLruYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/cache.lru.yao", size: 285, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/cache.lru.yao", size: 285, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -3020,7 +3020,7 @@ func yaoStoresKbCacheLruYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/kb/cache.lru.yao", size: 304, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/kb/cache.lru.yao", size: 304, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -3040,7 +3040,7 @@ func yaoStoresKbStoreBadgerYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/kb/store.badger.yao", size: 349, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/kb/store.badger.yao", size: 349, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -3060,7 +3060,7 @@ func yaoStoresOauthCacheLruYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/oauth/cache.lru.yao", size: 301, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/oauth/cache.lru.yao", size: 301, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -3080,7 +3080,7 @@ func yaoStoresOauthClientBadgerYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/oauth/client.badger.yao", size: 352, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/oauth/client.badger.yao", size: 352, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -3100,7 +3100,7 @@ func yaoStoresOauthStoreBadgerYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/oauth/store.badger.yao", size: 376, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/oauth/store.badger.yao", size: 376, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -3120,7 +3120,7 @@ func yaoStoresStoreBadgerYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/stores/store.badger.yao", size: 341, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/stores/store.badger.yao", size: 341, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -3140,7 +3140,7 @@ func yaoUploadersAttachmentLocalYao() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "yao/uploaders/attachment.local.yao", size: 1163, mode: os.FileMode(420), modTime: time.Unix(1765273963, 0)} + info := bindataFileInfo{name: "yao/uploaders/attachment.local.yao", size: 1163, mode: os.FileMode(420), modTime: time.Unix(1765337187, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/openapi/chat/session.go b/openapi/chat/session.go index 398b3bef..e61088d9 100644 --- a/openapi/chat/session.go +++ b/openapi/chat/session.go @@ -363,13 +363,59 @@ func GetMessages(c *gin.Context) { return } + // Get locale from query parameter or Accept-Language header + locale := getLocale(c) + + // Collect unique assistant IDs from messages and fetch their info + assistantIDs := collectAssistantIDs(messages) + assistants := assistant.GetInfoByIDs(assistantIDs, locale) + response.RespondWithSuccess(c, response.StatusOK, gin.H{ - "chat_id": chatID, - "messages": messages, - "count": len(messages), + "chat_id": chatID, + "messages": messages, + "count": len(messages), + "assistants": assistants, }) } +// getLocale extracts locale from request +// Priority: 1. Query param "locale", 2. Accept-Language header +func getLocale(c *gin.Context) string { + // Priority 1: Query parameter + if locale := c.Query("locale"); locale != "" { + return strings.ToLower(locale) + } + + // Priority 2: Header Accept-Language + if acceptLang := c.GetHeader("Accept-Language"); acceptLang != "" { + // Parse Accept-Language header (e.g., "en-US,en;q=0.9,zh;q=0.8") + // Take the first language + parts := strings.Split(acceptLang, ",") + if len(parts) > 0 { + // Remove quality value if present + lang := strings.Split(parts[0], ";")[0] + return strings.ToLower(strings.TrimSpace(lang)) + } + } + + return "" +} + +// collectAssistantIDs extracts unique assistant IDs from messages +func collectAssistantIDs(messages []*storetypes.Message) []string { + seen := make(map[string]bool) + var ids []string + + for _, msg := range messages { + if msg.AssistantID != "" && !seen[msg.AssistantID] { + seen[msg.AssistantID] = true + ids = append(ids, msg.AssistantID) + } + } + + return ids +} + // ============================================================================= // Helper Functions // ============================================================================= diff --git a/yao/models/agent/chat.mod.yao b/yao/models/agent/chat.mod.yao index 9bae8dd0..97fda5a9 100644 --- a/yao/models/agent/chat.mod.yao +++ b/yao/models/agent/chat.mod.yao @@ -50,13 +50,12 @@ "index": true }, { - "name": "mode", + "name": "last_mode", "type": "string", - "label": "Mode", - "comment": "Chat mode (default: chat)", + "label": "Last Mode", + "comment": "Last used chat mode (updated on each message)", "length": 50, - "nullable": false, - "default": "chat" + "nullable": true }, { "name": "status", diff --git a/yao/models/agent/message.mod.yao b/yao/models/agent/message.mod.yao index 5876ec47..1aff43dc 100644 --- a/yao/models/agent/message.mod.yao +++ b/yao/models/agent/message.mod.yao @@ -100,6 +100,14 @@ "nullable": true, "index": true }, + { + "name": "mode", + "type": "string", + "label": "Mode", + "comment": "Chat mode used for this message (chat or task)", + "length": 50, + "nullable": true + }, { "name": "sequence", "type": "integer",