diff --git a/agent/assistant/search.go b/agent/assistant/search.go
index 6e07bd72..da9c725c 100644
--- a/agent/assistant/search.go
+++ b/agent/assistant/search.go
@@ -119,6 +119,7 @@ func (ast *Assistant) executeAutoSearch(ctx *context.Context, messages []context
// 1. uses.keyword is configured (not empty)
// 2. Skip.Keyword is not true
// 3. Web search is enabled
+ var extractedKeywords []string
webSearchEnabled := searchConfig != nil && searchConfig.Web != nil
if webSearchEnabled && !skipKeyword && searchUses.Keyword != "" {
extractor := keyword.NewExtractor(searchUses.Keyword, searchConfig.Keyword)
@@ -126,12 +127,15 @@ func (ast *Assistant) executeAutoSearch(ctx *context.Context, messages []context
if err != nil {
ctx.Logger.Warn("Keyword extraction failed, using original query: %v", err)
} else if len(keywords) > 0 {
+ extractedKeywords = keywords
// Use extracted keywords as the search query for web search
optimizedQuery := strings.Join(keywords, " ")
ctx.Logger.Info("Extracted keywords for web search: %s -> %s", truncateString(query, 30), optimizedQuery)
query = optimizedQuery
}
}
+ // extractedKeywords will be used for storage in saveSearch() - TODO: Phase 1.9.5
+ _ = extractedKeywords
// Build search requests based on configuration
requests := ast.buildSearchRequests(query, searchConfig)
diff --git a/agent/i18n/builtin.go b/agent/i18n/builtin.go
index 7fd07a77..3aa2f04d 100644
--- a/agent/i18n/builtin.go
+++ b/agent/i18n/builtin.go
@@ -108,14 +108,14 @@ func init() {
"search.no_results": "No references found",
// Search: assistant/search.go - Trace labels
- "search.trace.label": "Search",
- "search.trace.description": "Search the web and knowledge base for relevant information",
- "search.trace.web.label": "Web Search",
- "search.trace.web.description": "Searching the web",
- "search.trace.kb.label": "KB Search",
- "search.trace.kb.description": "Searching knowledge base",
- "search.trace.db.label": "DB Search",
- "search.trace.db.description": "Searching database",
+ "search.trace.label": "Search",
+ "search.trace.description": "Search the web and knowledge base for relevant information",
+ "search.trace.web.label": "Web Search",
+ "search.trace.web.description": "Searching the web",
+ "search.trace.kb.label": "KB Search",
+ "search.trace.kb.description": "Searching knowledge base",
+ "search.trace.db.label": "DB Search",
+ "search.trace.db.description": "Searching database",
},
}
@@ -192,14 +192,14 @@ func init() {
"search.no_results": "未找到相关资料",
// Search: assistant/search.go - Trace labels
- "search.trace.label": "搜索",
- "search.trace.description": "搜索网络和知识库获取相关信息",
- "search.trace.web.label": "网页搜索",
- "search.trace.web.description": "搜索网页获取相关信息",
- "search.trace.kb.label": "知识库搜索",
- "search.trace.kb.description": "搜索知识库获取相关信息",
- "search.trace.db.label": "数据库搜索",
- "search.trace.db.description": "搜索数据库获取相关信息",
+ "search.trace.label": "搜索",
+ "search.trace.description": "搜索网络和知识库获取相关信息",
+ "search.trace.web.label": "网页搜索",
+ "search.trace.web.description": "搜索网页获取相关信息",
+ "search.trace.kb.label": "知识库搜索",
+ "search.trace.kb.description": "搜索知识库获取相关信息",
+ "search.trace.db.label": "数据库搜索",
+ "search.trace.db.description": "搜索数据库获取相关信息",
},
}
diff --git a/agent/search/DESIGN.md b/agent/search/DESIGN.md
index 3331cfb4..b30d9928 100644
--- a/agent/search/DESIGN.md
+++ b/agent/search/DESIGN.md
@@ -565,7 +565,7 @@ type RerankOptions struct {
TopN int `json:"top_n,omitempty"` // Return top N after reranking
}
-// Result represents the search result
+// Result represents the search result with all intermediate processing data
type Result struct {
Type SearchType `json:"type"` // Search type
Query string `json:"query"` // Original query
@@ -575,10 +575,31 @@ type Result struct {
Duration int64 `json:"duration_ms"` // Search duration in ms
Error string `json:"error,omitempty"` // Error message if failed
+ // Intermediate processing results (for storage and debugging)
+ Keywords []string `json:"keywords,omitempty"` // Extracted keywords (Web/NLP)
+ DSL map[string]any `json:"dsl,omitempty"` // Generated QueryDSL (DB)
+ Entities []Entity `json:"entities,omitempty"` // Extracted entities (Graph RAG)
+ Relations []Relation `json:"relations,omitempty"` // Extracted relations (Graph RAG)
+
// Graph associations (KB only, if enabled)
GraphNodes []*GraphNode `json:"graph_nodes,omitempty"`
}
+// Entity represents an extracted entity (for Graph RAG)
+type Entity struct {
+ Name string `json:"name"`
+ Type string `json:"type,omitempty"`
+ Source string `json:"source,omitempty"`
+}
+
+// Relation represents an extracted relation (for Graph RAG)
+type Relation struct {
+ Subject string `json:"subject"`
+ Predicate string `json:"predicate"`
+ Object string `json:"object"`
+ Source string `json:"source,omitempty"`
+}
+
// ResultItem represents a single search result item
type ResultItem struct {
// Citation
@@ -615,6 +636,43 @@ type ProcessedQuery struct {
Vector []float32 `json:"vector,omitempty"` // For KB search
DSL *gou.QueryDSL `json:"dsl,omitempty"` // For DB search, uses GOU QueryDSL
}
+```
+
+> **Design Note: Result with Intermediate Data**
+>
+> The `Result` type now includes intermediate processing results (`Keywords`, `DSL`, `Entities`, `Relations`)
+> that were previously only available during query processing. This design enables:
+>
+> 1. **Storage for Debugging**: All processing steps are captured for later analysis
+> 2. **System Tuning**: Analyze extracted keywords, generated DSL, and entity extraction quality
+> 3. **Unified Data Flow**: Handlers populate these fields during execution, eliminating the need
+> for separate data collection in `executeAutoSearch`
+>
+> **Handler Responsibilities**:
+>
+> - **Web Handler**: Populates `Keywords` from NLP extraction
+> - **DB Handler**: Populates `DSL` from QueryDSL generation
+> - **KB Handler**: Populates `Entities`, `Relations`, and `GraphNodes` from Graph RAG
+>
+> **Data Flow**:
+>
+> ```
+> Request → Handler → Result (with Keywords/DSL/Entities/Relations)
+> ↓
+> BuildReferenceContext
+> ↓
+> saveSearch (stores all intermediate data)
+> ```
+
+```go
+// ProcessedQuery is DEPRECATED for external use
+// Handlers should populate Result.Keywords/DSL/Entities/Relations directly
+type ProcessedQuery struct {
+ Type SearchType `json:"type"`
+ Keywords []string `json:"keywords,omitempty"` // For web search
+ Vector []float32 `json:"vector,omitempty"` // For KB search
+ DSL *gou.QueryDSL `json:"dsl,omitempty"` // For DB search
+}
// Note: For QueryDSL and Model types, use GOU types directly:
// - github.com/yaoapp/gou/query/gou.QueryDSL
@@ -1008,6 +1066,495 @@ Frame 3 - Removed:
(loading indicator removed when done: true)
```
+## Search Result Storage
+
+Search results are stored per request to support citation click-through and history replay.
+
+### Data Model
+
+```
+Relationships:
+Chat
+ └── Request (request_id)
+ ├── Message[] (user, assistant, tool...)
+ └── SearchResult[] (one request may have multiple searches)
+ └── Reference[] (indexed references from each search)
+```
+
+### Citation Locating
+
+LLM output uses `` tags with index:
+
+```xml
+AI is artificial intelligence, it has developed rapidly...
+```
+
+Location path: `request_id` + `index` → precisely locate reference
+
+### Database Schema
+
+**Table: `agent_search`**
+
+| Column | Type | Description |
+| ---------- | ----------- | -------------------------------------- |
+| id | BIGINT | Auto-increment primary key |
+| request_id | VARCHAR(64) | Associated request ID (indexed) |
+| chat_id | VARCHAR(64) | Associated chat ID (indexed) |
+| query | TEXT | Original search query |
+| config | JSON | Search config used (for tuning) |
+| keywords | JSON | Extracted keywords (from NLP) |
+| entities | JSON | Extracted entities (for Graph search) |
+| relations | JSON | Extracted relations (for Graph search) |
+| dsl | JSON | Generated QueryDSL (for DB search) |
+| source | VARCHAR(32) | Search source: web/kb/db/auto |
+| references | JSON | Reference[] with global index |
+| graph | JSON | GraphNode[] from knowledge graph |
+| xml | TEXT | Formatted XML for LLM context |
+| prompt | TEXT | Citation instruction prompt |
+| duration | INT | Search duration in milliseconds |
+| error | TEXT | Error message if failed (nullable) |
+| created_at | TIMESTAMP | Creation time |
+| deleted_at | TIMESTAMP | Soft delete time (nullable) |
+
+**Config Field Structure:**
+
+```json
+{
+ "uses": {
+ "search": "builtin",
+ "web": "builtin",
+ "keyword": "builtin",
+ "querydsl": "builtin",
+ "rerank": "builtin"
+ },
+ "web": {
+ "provider": "tavily",
+ "max_results": 5
+ },
+ "kb": {
+ "collections": ["docs", "faq"],
+ "threshold": 0.7,
+ "graph": true
+ },
+ "db": {
+ "models": ["product", "order"],
+ "max_results": 20
+ },
+ "rerank": {
+ "provider": "builtin",
+ "top_n": 10
+ }
+}
+```
+
+### Type Definitions
+
+```go
+// store/types/types.go
+
+// Search represents stored search results for a request
+// Stores all intermediate processing results for debugging and replay
+type Search struct {
+ ID int64 `json:"id"`
+ RequestID string `json:"request_id"`
+ ChatID string `json:"chat_id"`
+ Query string `json:"query"` // Original query
+ Config map[string]any `json:"config,omitempty"` // Search config used (for tuning)
+ Keywords []string `json:"keywords,omitempty"` // Extracted keywords (Web/NLP)
+ Entities []Entity `json:"entities,omitempty"` // Extracted entities (Graph)
+ Relations []Relation `json:"relations,omitempty"` // Extracted relations (Graph)
+ DSL map[string]any `json:"dsl,omitempty"` // Generated QueryDSL (DB)
+ Source string `json:"source"` // web/kb/db/auto
+ References []Reference `json:"references"`
+ Graph []GraphNode `json:"graph,omitempty"` // Graph nodes from KB
+ XML string `json:"xml,omitempty"` // Formatted XML for LLM
+ Prompt string `json:"prompt,omitempty"` // Citation prompt
+ Duration int64 `json:"duration_ms"` // Search duration
+ Error string `json:"error,omitempty"` // Error if failed
+ CreatedAt time.Time `json:"created_at"`
+}
+
+// Reference represents a single reference with global index (for storage)
+type Reference struct {
+ Index int `json:"index"` // Global index: 1, 2, 3...
+ Type string `json:"type"` // web/kb/db
+ Title string `json:"title"`
+ URL string `json:"url,omitempty"`
+ Snippet string `json:"snippet"`
+ Content string `json:"content,omitempty"` // Full content (optional)
+ Metadata map[string]any `json:"metadata,omitempty"`
+}
+
+// Entity represents an extracted entity from query (for Graph search)
+type Entity struct {
+ Name string `json:"name"` // Entity name
+ Type string `json:"type"` // Entity type: person, org, location, etc.
+ Metadata map[string]any `json:"metadata,omitempty"`
+}
+
+// Relation represents an extracted relation from query (for Graph search)
+type Relation struct {
+ Subject string `json:"subject"` // Source entity
+ Predicate string `json:"predicate"` // Relation type
+ Object string `json:"object"` // Target entity
+ Metadata map[string]any `json:"metadata,omitempty"`
+}
+
+// GraphNode represents a node from knowledge graph (search result)
+type GraphNode struct {
+ ID string `json:"id"`
+ Type string `json:"type"` // Entity type
+ Name string `json:"name"` // Entity name
+ Description string `json:"description,omitempty"`
+ Relation string `json:"relation,omitempty"` // Relationship to query
+ Score float64 `json:"score,omitempty"`
+ Metadata map[string]any `json:"metadata,omitempty"`
+}
+
+// SearchFilter for querying search records
+type SearchFilter struct {
+ RequestID string `json:"request_id,omitempty"`
+ ChatID string `json:"chat_id,omitempty"`
+ Source string `json:"source,omitempty"`
+}
+```
+
+### Store Interface Extension
+
+```go
+// store/types/store.go
+
+// ChatStore interface extension
+type ChatStore interface {
+ // ... existing methods ...
+
+ // ==========================================================================
+ // Search Management
+ // ==========================================================================
+
+ // SaveSearch saves search record for a request
+ // search: Search record to save
+ // Returns: Potential error
+ SaveSearch(search *Search) error
+
+ // GetSearches retrieves search records for a request
+ // requestID: Request ID
+ // Returns: Search records and potential error
+ GetSearches(requestID string) ([]*Search, error)
+
+ // GetReference retrieves a single reference by request ID and index
+ // requestID: Request ID
+ // index: Reference index (1-based)
+ // Returns: Reference and potential error
+ GetReference(requestID string, index int) (*Reference, error)
+
+ // DeleteSearches deletes all search records for a chat
+ // chatID: Chat ID
+ // Returns: Potential error
+ DeleteSearches(chatID string) error
+}
+```
+
+### Xun Implementation
+
+```go
+// store/xun/search.go
+
+// SaveSearch saves a search record
+func (store *Xun) SaveSearch(search *Search) error {
+ if search.RequestID == "" {
+ return fmt.Errorf("request_id is required")
+ }
+
+ refsJSON, err := jsoniter.MarshalToString(search.References)
+ if err != nil {
+ return fmt.Errorf("failed to marshal references: %w", err)
+ }
+
+ row := map[string]interface{}{
+ "request_id": search.RequestID,
+ "chat_id": search.ChatID,
+ "query": search.Query,
+ "config": search.Config, // Search config for tuning
+ "keywords": search.Keywords,
+ "entities": search.Entities, // Graph entities
+ "relations": search.Relations, // Graph relations
+ "dsl": search.DSL,
+ "source": search.Source,
+ "references": refsJSON,
+ "graph": search.Graph, // Graph nodes
+ "xml": search.XML,
+ "prompt": search.Prompt,
+ "duration": search.Duration,
+ "error": search.Error,
+ "created_at": time.Now(),
+ }
+
+ return store.newQuerySearch().Insert(row)
+}
+
+// GetSearches retrieves all search records for a request
+func (store *Xun) GetSearches(requestID string) ([]*Search, error) {
+ rows, err := store.newQuerySearch().
+ Where("request_id", requestID).
+ WhereNull("deleted_at").
+ OrderBy("created_at", "asc").
+ Get()
+ // ... convert rows to Search
+}
+
+// GetReference retrieves a single reference
+func (store *Xun) GetReference(requestID string, index int) (*Reference, error) {
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ return nil, err
+ }
+
+ // Find reference by index across all search records
+ for _, search := range searches {
+ for _, ref := range search.References {
+ if ref.Index == index {
+ return &ref, nil
+ }
+ }
+ }
+
+ return nil, fmt.Errorf("reference %d not found in request %s", index, requestID)
+}
+```
+
+### Model Definition
+
+```json
+// yao/models/agent/search.mod.yao
+{
+ "name": "Search",
+ "label": "Search",
+ "description": "Search records for citation support and debugging",
+ "tags": ["agent", "system"],
+ "builtin": true,
+ "readonly": true,
+ "table": {
+ "name": "agent_search",
+ "comment": "Agent search table"
+ },
+ "columns": [
+ { "name": "id", "type": "ID", "label": "ID" },
+ {
+ "name": "request_id",
+ "type": "string",
+ "length": 64,
+ "nullable": false,
+ "index": true
+ },
+ {
+ "name": "chat_id",
+ "type": "string",
+ "length": 64,
+ "nullable": false,
+ "index": true
+ },
+ { "name": "query", "type": "text", "nullable": true },
+ {
+ "name": "config",
+ "type": "json",
+ "nullable": true,
+ "comment": "Search config used (for tuning)"
+ },
+ { "name": "keywords", "type": "json", "nullable": true },
+ { "name": "entities", "type": "json", "nullable": true },
+ { "name": "relations", "type": "json", "nullable": true },
+ { "name": "dsl", "type": "json", "nullable": true },
+ { "name": "source", "type": "string", "length": 32, "nullable": false },
+ { "name": "references", "type": "json", "nullable": true },
+ { "name": "graph", "type": "json", "nullable": true },
+ { "name": "xml", "type": "text", "nullable": true },
+ { "name": "prompt", "type": "text", "nullable": true },
+ { "name": "duration", "type": "integer", "nullable": true },
+ { "name": "error", "type": "text", "nullable": true }
+ ],
+ "option": { "timestamps": true, "soft_deletes": true }
+}
+```
+
+### Stream Integration
+
+Storage logic is encapsulated in `assistant/search.go` with a dedicated method:
+
+```go
+// assistant/search.go
+
+// SearchExecutionResult contains all intermediate results from search execution
+type SearchExecutionResult struct {
+ Query string // Original query
+ Config map[string]any // Search config used
+ Keywords []string // Extracted keywords (Web/NLP)
+ Entities []storeTypes.Entity // Extracted entities (Graph)
+ Relations []storeTypes.Relation // Extracted relations (Graph)
+ DSL map[string]any // Generated QueryDSL (DB)
+ Source string // web/kb/db/auto
+ RefCtx *searchTypes.ReferenceContext // Reference context for LLM
+ Graph []storeTypes.GraphNode // Graph nodes from KB
+ Duration int64 // Duration in ms
+ Error string // Error message if failed
+}
+
+// saveSearch saves search record to store for citation support and debugging
+func (ast *Assistant) saveSearch(ctx *context.Context, result *SearchExecutionResult) {
+ if ctx.Store == nil || result == nil {
+ return
+ }
+
+ // Skip if no references and no error
+ if result.RefCtx == nil && result.Error == "" {
+ return
+ }
+
+ var refs []storeTypes.Reference
+ var xml, prompt string
+
+ if result.RefCtx != nil {
+ refs = convertReferences(result.RefCtx.References)
+ xml = result.RefCtx.XML
+ prompt = result.RefCtx.Prompt
+ }
+
+ search := &storeTypes.Search{
+ RequestID: ctx.RequestID,
+ ChatID: ctx.ID,
+ Query: result.Query,
+ Config: result.Config, // Search config for tuning analysis
+ Keywords: result.Keywords,
+ Entities: result.Entities, // Graph entities
+ Relations: result.Relations, // Graph relations
+ DSL: result.DSL,
+ Source: result.Source,
+ References: refs,
+ Graph: result.Graph, // Graph nodes
+ XML: xml,
+ Prompt: prompt,
+ Duration: result.Duration,
+ Error: result.Error,
+ }
+
+ if err := ctx.Store.SaveSearch(search); err != nil {
+ ctx.Logger.Warn("Failed to save search: %v", err)
+ }
+}
+
+// convertReferences converts search references to store format
+func convertReferences(refs []*searchTypes.Reference) []storeTypes.Reference {
+ result := make([]storeTypes.Reference, len(refs))
+ for i, ref := range refs {
+ result[i] = storeTypes.Reference{
+ Index: i + 1, // 1-based index
+ Type: string(ref.Type),
+ Title: ref.Title,
+ URL: ref.URL,
+ Snippet: ref.Content,
+ Content: ref.Content,
+ Metadata: ref.Meta,
+ }
+ }
+ return result
+}
+
+// In executeAutoSearch:
+func (ast *Assistant) executeAutoSearch(ctx *context.Context, ...) *searchTypes.ReferenceContext {
+ start := time.Now()
+
+ // 1. Execute search (Result now contains all intermediate data)
+ results, err := searcher.All(ctx, requests)
+ duration := time.Since(start).Milliseconds()
+
+ // 2. Prepare execution result for storage
+ execResult := &SearchExecutionResult{
+ Query: query,
+ Config: buildSearchConfig(searchConfig, searchUses),
+ Source: "auto",
+ Duration: duration,
+ }
+
+ if err != nil {
+ execResult.Error = err.Error()
+ ast.saveSearch(ctx, execResult)
+ return nil
+ }
+
+ // 3. Extract intermediate data from results
+ // Result.Keywords, Result.DSL, Result.Entities, Result.Relations are populated by handlers
+ for _, result := range results {
+ if len(result.Keywords) > 0 {
+ execResult.Keywords = result.Keywords
+ }
+ if result.DSL != nil {
+ execResult.DSL = result.DSL
+ }
+ if len(result.Entities) > 0 {
+ execResult.Entities = convertEntities(result.Entities)
+ }
+ if len(result.Relations) > 0 {
+ execResult.Relations = convertRelations(result.Relations)
+ }
+ if len(result.GraphNodes) > 0 {
+ execResult.Graph = convertGraphNodes(result.GraphNodes)
+ }
+ }
+
+ // 4. Build reference context
+ refCtx := search.BuildReferenceContext(results, citationConfig)
+ execResult.RefCtx = refCtx
+
+ // 5. Save search record
+ ast.saveSearch(ctx, execResult)
+
+ return refCtx
+}
+```
+
+### Usage Scenarios
+
+**Scenario 1: Single Search**
+
+```
+Request: req_001
+ └── Search: { source: "auto", references: [{index:1,...}, {index:2,...}, {index:3,...}] }
+```
+
+**Scenario 2: Multiple Searches (e.g., Tool Call triggers another search)**
+
+```
+Request: req_001
+ ├── Search[0]: { source: "web", references: [{index:1,...}, {index:2,...}] }
+ └── Search[1]: { source: "kb", references: [{index:3,...}, {index:4,...}] }
+```
+
+Index is globally incremented, so `request_id + index` is always unique.
+
+### API Endpoints
+
+```
+GET /api/chat/{chat_id}/request/{request_id}/references # Get all references for request
+GET /api/chat/{chat_id}/request/{request_id}/reference/{index} # Get single reference by index
+```
+
+### Frontend Integration
+
+```typescript
+// When user clicks citation [1]
+async function onCitationClick(requestId: string, index: number) {
+ const ref = await api.get(
+ `/chat/${chatId}/request/${requestId}/reference/${index}`
+ );
+ showReferenceCard({
+ title: ref.title,
+ url: ref.url,
+ snippet: ref.snippet,
+ content: ref.content,
+ });
+}
+```
+
## JSAPI Integration
The Search module is exposed via `ctx.search` object in hook scripts.
diff --git a/agent/store/mongo/mongo.go b/agent/store/mongo/mongo.go
index 30e4970d..bd910a09 100644
--- a/agent/store/mongo/mongo.go
+++ b/agent/store/mongo/mongo.go
@@ -157,3 +157,31 @@ func (m *Mongo) DeleteAssistants(filter types.AssistantFilter) (int64, error) {
// TODO: implement
return 0, nil
}
+
+// =============================================================================
+// Search Management
+// =============================================================================
+
+// SaveSearch saves a search record for a request
+func (m *Mongo) SaveSearch(search *types.Search) error {
+ // TODO: implement
+ return nil
+}
+
+// GetSearches retrieves all search records for a request
+func (m *Mongo) GetSearches(requestID string) ([]*types.Search, error) {
+ // TODO: implement
+ return nil, nil
+}
+
+// GetReference retrieves a single reference by request ID and index
+func (m *Mongo) GetReference(requestID string, index int) (*types.Reference, error) {
+ // TODO: implement
+ return nil, nil
+}
+
+// DeleteSearches deletes all search records for a chat
+func (m *Mongo) DeleteSearches(chatID string) error {
+ // TODO: implement
+ return nil
+}
diff --git a/agent/store/redis/redis.go b/agent/store/redis/redis.go
index 99c2889b..ef9683f1 100644
--- a/agent/store/redis/redis.go
+++ b/agent/store/redis/redis.go
@@ -157,3 +157,31 @@ func (r *Redis) DeleteAssistants(filter types.AssistantFilter) (int64, error) {
// TODO: implement
return 0, nil
}
+
+// =============================================================================
+// Search Management
+// =============================================================================
+
+// SaveSearch saves a search record for a request
+func (r *Redis) SaveSearch(search *types.Search) error {
+ // TODO: implement
+ return nil
+}
+
+// GetSearches retrieves all search records for a request
+func (r *Redis) GetSearches(requestID string) ([]*types.Search, error) {
+ // TODO: implement
+ return nil, nil
+}
+
+// GetReference retrieves a single reference by request ID and index
+func (r *Redis) GetReference(requestID string, index int) (*types.Reference, error) {
+ // TODO: implement
+ return nil, nil
+}
+
+// DeleteSearches deletes all search records for a chat
+func (r *Redis) DeleteSearches(chatID string) error {
+ // TODO: implement
+ return nil
+}
diff --git a/agent/store/types/store.go b/agent/store/types/store.go
index d9e40fa7..99afc8e7 100644
--- a/agent/store/types/store.go
+++ b/agent/store/types/store.go
@@ -98,6 +98,34 @@ type ChatStore interface {
// chatID: Chat ID
// Returns: Potential error
DeleteResume(chatID string) error
+
+ // ==========================================================================
+ // Search Management
+ // ==========================================================================
+
+ // SaveSearch saves a search record for a request
+ // Used for citation support, debugging, and replay
+ // search: Search record to save
+ // Returns: Potential error
+ SaveSearch(search *Search) error
+
+ // GetSearches retrieves all search records for a request
+ // requestID: Request ID
+ // Returns: Search records and potential error
+ GetSearches(requestID string) ([]*Search, error)
+
+ // GetReference retrieves a single reference by request ID and index
+ // Used for citation click handling
+ // requestID: Request ID
+ // index: Reference index (1-based)
+ // Returns: Reference and potential error
+ GetReference(requestID string, index int) (*Reference, error)
+
+ // DeleteSearches deletes all search records for a chat
+ // Called when deleting a chat
+ // chatID: Chat ID
+ // Returns: Potential error
+ DeleteSearches(chatID string) error
}
// AssistantStore defines the assistant storage interface
diff --git a/agent/store/types/types.go b/agent/store/types/types.go
index f5465c13..7ada83e5 100644
--- a/agent/store/types/types.go
+++ b/agent/store/types/types.go
@@ -447,3 +447,71 @@ type AssistantModel struct {
YaoTeamID string `json:"-"` // Team ID for team-based access control (not exposed in JSON)
YaoTenantID string `json:"-"` // Tenant ID for multi-tenancy support (not exposed in JSON)
}
+
+// =============================================================================
+// Search Types (for search result storage)
+// =============================================================================
+
+// Search represents stored search results for a request
+// Stores all intermediate processing results for debugging, replay, and citation
+type Search struct {
+ ID int64 `json:"id"`
+ RequestID string `json:"request_id"`
+ ChatID string `json:"chat_id"`
+ Query string `json:"query"` // Original query
+ Config map[string]any `json:"config,omitempty"` // Search config used (for tuning)
+ Keywords []string `json:"keywords,omitempty"` // Extracted keywords (Web/NLP)
+ Entities []Entity `json:"entities,omitempty"` // Extracted entities (Graph)
+ Relations []Relation `json:"relations,omitempty"` // Extracted relations (Graph)
+ DSL map[string]any `json:"dsl,omitempty"` // Generated QueryDSL (DB)
+ Source string `json:"source"` // web/kb/db/auto
+ References []Reference `json:"references"` // References with global index
+ Graph []GraphNode `json:"graph,omitempty"` // Graph nodes from KB
+ XML string `json:"xml,omitempty"` // Formatted XML for LLM
+ Prompt string `json:"prompt,omitempty"` // Citation prompt
+ Duration int64 `json:"duration_ms"` // Search duration in ms
+ Error string `json:"error,omitempty"` // Error if failed
+ CreatedAt time.Time `json:"created_at"`
+}
+
+// Reference represents a single reference with global index (for storage)
+type Reference struct {
+ Index int `json:"index"` // Global index (1-based, unique within request)
+ Type string `json:"type"` // web/kb/db
+ Title string `json:"title"` // Reference title
+ URL string `json:"url,omitempty"` // URL (for web)
+ Snippet string `json:"snippet,omitempty"` // Short snippet
+ Content string `json:"content,omitempty"` // Full content
+ Metadata map[string]any `json:"metadata,omitempty"`
+}
+
+// SearchFilter for listing searches
+type SearchFilter struct {
+ RequestID string `json:"request_id,omitempty"`
+ ChatID string `json:"chat_id,omitempty"`
+ Source string `json:"source,omitempty"`
+}
+
+// Entity represents an extracted entity (for Graph RAG)
+type Entity struct {
+ Name string `json:"name"`
+ Type string `json:"type,omitempty"`
+ Source string `json:"source,omitempty"`
+}
+
+// Relation represents an extracted relation (for Graph RAG)
+type Relation struct {
+ Subject string `json:"subject"`
+ Predicate string `json:"predicate"`
+ Object string `json:"object"`
+ Source string `json:"source,omitempty"`
+}
+
+// GraphNode represents a node from knowledge graph
+type GraphNode struct {
+ ID string `json:"id"`
+ Type string `json:"type"`
+ Label string `json:"label,omitempty"`
+ Properties map[string]any `json:"properties,omitempty"`
+ Score float64 `json:"score,omitempty"`
+}
diff --git a/agent/store/xun/search.go b/agent/store/xun/search.go
new file mode 100644
index 00000000..8ed1043b
--- /dev/null
+++ b/agent/store/xun/search.go
@@ -0,0 +1,301 @@
+package xun
+
+import (
+ "fmt"
+ "time"
+
+ jsoniter "github.com/json-iterator/go"
+ "github.com/yaoapp/gou/model"
+ "github.com/yaoapp/xun/dbal/query"
+ "github.com/yaoapp/yao/agent/store/types"
+)
+
+// =============================================================================
+// Search Management
+// =============================================================================
+
+// SaveSearch saves a search record for a request
+func (store *Xun) SaveSearch(search *types.Search) error {
+ if search == nil {
+ return fmt.Errorf("search is nil")
+ }
+ if search.RequestID == "" {
+ return fmt.Errorf("request_id is required")
+ }
+ if search.ChatID == "" {
+ return fmt.Errorf("chat_id is required")
+ }
+ if search.Source == "" {
+ return fmt.Errorf("source is required")
+ }
+
+ now := time.Now()
+
+ // Build row data
+ row := map[string]interface{}{
+ "request_id": search.RequestID,
+ "chat_id": search.ChatID,
+ "query": search.Query,
+ "source": search.Source,
+ "duration": search.Duration,
+ "created_at": now,
+ "updated_at": now,
+ }
+
+ // Handle JSON fields
+ if search.Config != nil {
+ configJSON, err := jsoniter.MarshalToString(search.Config)
+ if err != nil {
+ return fmt.Errorf("failed to marshal config: %w", err)
+ }
+ row["config"] = configJSON
+ }
+
+ if len(search.Keywords) > 0 {
+ keywordsJSON, err := jsoniter.MarshalToString(search.Keywords)
+ if err != nil {
+ return fmt.Errorf("failed to marshal keywords: %w", err)
+ }
+ row["keywords"] = keywordsJSON
+ }
+
+ if len(search.Entities) > 0 {
+ entitiesJSON, err := jsoniter.MarshalToString(search.Entities)
+ if err != nil {
+ return fmt.Errorf("failed to marshal entities: %w", err)
+ }
+ row["entities"] = entitiesJSON
+ }
+
+ if len(search.Relations) > 0 {
+ relationsJSON, err := jsoniter.MarshalToString(search.Relations)
+ if err != nil {
+ return fmt.Errorf("failed to marshal relations: %w", err)
+ }
+ row["relations"] = relationsJSON
+ }
+
+ if search.DSL != nil {
+ dslJSON, err := jsoniter.MarshalToString(search.DSL)
+ if err != nil {
+ return fmt.Errorf("failed to marshal dsl: %w", err)
+ }
+ row["dsl"] = dslJSON
+ }
+
+ if len(search.References) > 0 {
+ refsJSON, err := jsoniter.MarshalToString(search.References)
+ if err != nil {
+ return fmt.Errorf("failed to marshal references: %w", err)
+ }
+ row["references"] = refsJSON
+ }
+
+ if len(search.Graph) > 0 {
+ graphJSON, err := jsoniter.MarshalToString(search.Graph)
+ if err != nil {
+ return fmt.Errorf("failed to marshal graph: %w", err)
+ }
+ row["graph"] = graphJSON
+ }
+
+ if search.XML != "" {
+ row["xml"] = search.XML
+ }
+
+ if search.Prompt != "" {
+ row["prompt"] = search.Prompt
+ }
+
+ if search.Error != "" {
+ row["error"] = search.Error
+ }
+
+ return store.newQuerySearch().Insert(row)
+}
+
+// GetSearches retrieves all search records for a request
+func (store *Xun) GetSearches(requestID string) ([]*types.Search, error) {
+ if requestID == "" {
+ return nil, fmt.Errorf("request_id is required")
+ }
+
+ rows, err := store.newQuerySearch().
+ Where("request_id", requestID).
+ WhereNull("deleted_at").
+ OrderBy("created_at", "asc").
+ Get()
+ if err != nil {
+ return nil, err
+ }
+
+ searches := make([]*types.Search, 0, len(rows))
+ for _, row := range rows {
+ data := row.ToMap()
+ if data == nil {
+ continue
+ }
+
+ search, err := store.rowToSearch(data)
+ if err != nil {
+ continue
+ }
+ searches = append(searches, search)
+ }
+
+ return searches, nil
+}
+
+// GetReference retrieves a single reference by request ID and index
+func (store *Xun) GetReference(requestID string, index int) (*types.Reference, error) {
+ if requestID == "" {
+ return nil, fmt.Errorf("request_id is required")
+ }
+ if index < 1 {
+ return nil, fmt.Errorf("index must be >= 1")
+ }
+
+ // Get all searches for this request
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ return nil, err
+ }
+
+ // Find the reference with matching index
+ for _, search := range searches {
+ for _, ref := range search.References {
+ if ref.Index == index {
+ return &ref, nil
+ }
+ }
+ }
+
+ return nil, fmt.Errorf("reference not found: request_id=%s, index=%d", requestID, index)
+}
+
+// DeleteSearches deletes all search records for a chat (soft delete)
+func (store *Xun) DeleteSearches(chatID string) error {
+ if chatID == "" {
+ return fmt.Errorf("chat_id is required")
+ }
+
+ _, err := store.newQuerySearch().
+ Where("chat_id", chatID).
+ WhereNull("deleted_at").
+ Update(map[string]interface{}{
+ "deleted_at": time.Now(),
+ "updated_at": time.Now(),
+ })
+
+ return err
+}
+
+// =============================================================================
+// Query Builder
+// =============================================================================
+
+// newQuerySearch creates a new query builder for the search table
+func (store *Xun) newQuerySearch() query.Query {
+ qb := store.query.New()
+ qb.Table(store.getSearchTable())
+ return qb
+}
+
+// getSearchTable returns the search table name
+func (store *Xun) getSearchTable() string {
+ m := model.Select("__yao.agent.search")
+ if m != nil && m.MetaData.Table.Name != "" {
+ return m.MetaData.Table.Name
+ }
+ return "agent_search"
+}
+
+// =============================================================================
+// Helper Functions
+// =============================================================================
+
+// rowToSearch converts a database row to a Search struct
+func (store *Xun) rowToSearch(data map[string]interface{}) (*types.Search, error) {
+ search := &types.Search{
+ ID: getInt64(data, "id"),
+ RequestID: getString(data, "request_id"),
+ ChatID: getString(data, "chat_id"),
+ Query: getString(data, "query"),
+ Source: getString(data, "source"),
+ XML: getString(data, "xml"),
+ Prompt: getString(data, "prompt"),
+ Duration: getInt64(data, "duration"),
+ Error: getString(data, "error"),
+ }
+
+ // Handle timestamps
+ if createdAt := getTime(data, "created_at"); createdAt != nil {
+ search.CreatedAt = *createdAt
+ }
+
+ // Parse JSON fields
+ if config := data["config"]; config != nil {
+ if configStr, ok := config.(string); ok && configStr != "" {
+ var configMap map[string]any
+ if err := jsoniter.UnmarshalFromString(configStr, &configMap); err == nil {
+ search.Config = configMap
+ }
+ }
+ }
+
+ if keywords := data["keywords"]; keywords != nil {
+ if keywordsStr, ok := keywords.(string); ok && keywordsStr != "" {
+ var keywordsList []string
+ if err := jsoniter.UnmarshalFromString(keywordsStr, &keywordsList); err == nil {
+ search.Keywords = keywordsList
+ }
+ }
+ }
+
+ if entities := data["entities"]; entities != nil {
+ if entitiesStr, ok := entities.(string); ok && entitiesStr != "" {
+ var entitiesList []types.Entity
+ if err := jsoniter.UnmarshalFromString(entitiesStr, &entitiesList); err == nil {
+ search.Entities = entitiesList
+ }
+ }
+ }
+
+ if relations := data["relations"]; relations != nil {
+ if relationsStr, ok := relations.(string); ok && relationsStr != "" {
+ var relationsList []types.Relation
+ if err := jsoniter.UnmarshalFromString(relationsStr, &relationsList); err == nil {
+ search.Relations = relationsList
+ }
+ }
+ }
+
+ if dsl := data["dsl"]; dsl != nil {
+ if dslStr, ok := dsl.(string); ok && dslStr != "" {
+ var dslMap map[string]any
+ if err := jsoniter.UnmarshalFromString(dslStr, &dslMap); err == nil {
+ search.DSL = dslMap
+ }
+ }
+ }
+
+ if refs := data["references"]; refs != nil {
+ if refsStr, ok := refs.(string); ok && refsStr != "" {
+ var refsList []types.Reference
+ if err := jsoniter.UnmarshalFromString(refsStr, &refsList); err == nil {
+ search.References = refsList
+ }
+ }
+ }
+
+ if graph := data["graph"]; graph != nil {
+ if graphStr, ok := graph.(string); ok && graphStr != "" {
+ var graphList []types.GraphNode
+ if err := jsoniter.UnmarshalFromString(graphStr, &graphList); err == nil {
+ search.Graph = graphList
+ }
+ }
+ }
+
+ return search, nil
+}
diff --git a/agent/store/xun/search_test.go b/agent/store/xun/search_test.go
new file mode 100644
index 00000000..60d7b912
--- /dev/null
+++ b/agent/store/xun/search_test.go
@@ -0,0 +1,715 @@
+package xun_test
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/yaoapp/yao/agent/store/types"
+ "github.com/yaoapp/yao/agent/store/xun"
+ "github.com/yaoapp/yao/config"
+ "github.com/yaoapp/yao/test"
+)
+
+// TestSaveSearch tests saving search records
+func TestSaveSearch(t *testing.T) {
+ test.Prepare(t, config.Conf)
+ defer test.Clean()
+
+ store, err := xun.NewXun(types.Setting{
+ Connector: "default",
+ })
+ if err != nil {
+ t.Fatalf("Failed to create store: %v", err)
+ }
+
+ // Create a chat first
+ chat := &types.Chat{
+ AssistantID: "test_assistant",
+ Title: "Search Test Chat",
+ }
+ err = store.CreateChat(chat)
+ if err != nil {
+ t.Fatalf("Failed to create chat: %v", err)
+ }
+ defer store.DeleteChat(chat.ChatID)
+
+ t.Run("SaveBasicSearch", func(t *testing.T) {
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "What is the weather today?",
+ Source: "web",
+ Duration: 150,
+ }
+
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ // Verify
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 1 {
+ t.Fatalf("Expected 1 search, got %d", len(searches))
+ }
+
+ if searches[0].Query != "What is the weather today?" {
+ t.Errorf("Expected query 'What is the weather today?', got '%s'", searches[0].Query)
+ }
+ if searches[0].Source != "web" {
+ t.Errorf("Expected source 'web', got '%s'", searches[0].Source)
+ }
+ if searches[0].Duration != 150 {
+ t.Errorf("Expected duration 150, got %d", searches[0].Duration)
+ }
+ })
+
+ t.Run("SaveSearchWithKeywords", func(t *testing.T) {
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "Latest news about AI",
+ Keywords: []string{"AI", "news", "latest"},
+ Source: "web",
+ Duration: 200,
+ }
+
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 1 {
+ t.Fatalf("Expected 1 search, got %d", len(searches))
+ }
+
+ if len(searches[0].Keywords) != 3 {
+ t.Errorf("Expected 3 keywords, got %d", len(searches[0].Keywords))
+ }
+ if searches[0].Keywords[0] != "AI" {
+ t.Errorf("Expected first keyword 'AI', got '%s'", searches[0].Keywords[0])
+ }
+ })
+
+ t.Run("SaveSearchWithReferences", func(t *testing.T) {
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "How to learn Go programming?",
+ Source: "web",
+ References: []types.Reference{
+ {
+ Index: 1,
+ Type: "web",
+ Title: "Go Programming Tutorial",
+ URL: "https://go.dev/tour/",
+ Snippet: "An interactive introduction to Go",
+ },
+ {
+ Index: 2,
+ Type: "web",
+ Title: "Effective Go",
+ URL: "https://go.dev/doc/effective_go",
+ Snippet: "Tips for writing clear, idiomatic Go code",
+ },
+ },
+ XML: "...",
+ Prompt: "Please cite sources using [1], [2]...",
+ Duration: 300,
+ }
+
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 1 {
+ t.Fatalf("Expected 1 search, got %d", len(searches))
+ }
+
+ if len(searches[0].References) != 2 {
+ t.Errorf("Expected 2 references, got %d", len(searches[0].References))
+ }
+ if searches[0].References[0].Title != "Go Programming Tutorial" {
+ t.Errorf("Expected first reference title 'Go Programming Tutorial', got '%s'", searches[0].References[0].Title)
+ }
+ if searches[0].XML != "..." {
+ t.Errorf("Expected XML '...', got '%s'", searches[0].XML)
+ }
+ if searches[0].Prompt != "Please cite sources using [1], [2]..." {
+ t.Errorf("Expected prompt to be set")
+ }
+ })
+
+ t.Run("SaveSearchWithConfig", func(t *testing.T) {
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "Config test",
+ Source: "auto",
+ Config: map[string]any{
+ "uses": map[string]any{
+ "search": "builtin",
+ "web": "builtin",
+ "keyword": "builtin",
+ },
+ "web": map[string]any{
+ "provider": "tavily",
+ "max_results": 5,
+ },
+ },
+ Duration: 100,
+ }
+
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 1 {
+ t.Fatalf("Expected 1 search, got %d", len(searches))
+ }
+
+ if searches[0].Config == nil {
+ t.Fatal("Expected config to be set")
+ }
+ uses, ok := searches[0].Config["uses"].(map[string]any)
+ if !ok {
+ t.Fatal("Expected uses in config")
+ }
+ if uses["search"] != "builtin" {
+ t.Errorf("Expected uses.search='builtin', got '%v'", uses["search"])
+ }
+ })
+
+ t.Run("SaveSearchWithEntitiesAndRelations", func(t *testing.T) {
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "Who is the CEO of Apple?",
+ Source: "kb",
+ Entities: []types.Entity{
+ {Name: "Apple", Type: "Organization"},
+ {Name: "Tim Cook", Type: "Person"},
+ },
+ Relations: []types.Relation{
+ {Subject: "Tim Cook", Predicate: "CEO_of", Object: "Apple"},
+ },
+ Graph: []types.GraphNode{
+ {ID: "node1", Type: "Organization", Label: "Apple", Score: 0.95},
+ {ID: "node2", Type: "Person", Label: "Tim Cook", Score: 0.92},
+ },
+ Duration: 250,
+ }
+
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 1 {
+ t.Fatalf("Expected 1 search, got %d", len(searches))
+ }
+
+ if len(searches[0].Entities) != 2 {
+ t.Errorf("Expected 2 entities, got %d", len(searches[0].Entities))
+ }
+ if searches[0].Entities[0].Name != "Apple" {
+ t.Errorf("Expected first entity 'Apple', got '%s'", searches[0].Entities[0].Name)
+ }
+
+ if len(searches[0].Relations) != 1 {
+ t.Errorf("Expected 1 relation, got %d", len(searches[0].Relations))
+ }
+ if searches[0].Relations[0].Predicate != "CEO_of" {
+ t.Errorf("Expected predicate 'CEO_of', got '%s'", searches[0].Relations[0].Predicate)
+ }
+
+ if len(searches[0].Graph) != 2 {
+ t.Errorf("Expected 2 graph nodes, got %d", len(searches[0].Graph))
+ }
+ })
+
+ t.Run("SaveSearchWithDSL", func(t *testing.T) {
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "Find orders over $1000",
+ Source: "db",
+ DSL: map[string]any{
+ "wheres": []map[string]any{
+ {"column": "amount", "op": ">", "value": 1000},
+ },
+ "orders": []map[string]any{
+ {"column": "created_at", "option": "desc"},
+ },
+ },
+ Duration: 50,
+ }
+
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 1 {
+ t.Fatalf("Expected 1 search, got %d", len(searches))
+ }
+
+ if searches[0].DSL == nil {
+ t.Fatal("Expected DSL to be set")
+ }
+ wheres, ok := searches[0].DSL["wheres"].([]any)
+ if !ok || len(wheres) == 0 {
+ t.Error("Expected wheres in DSL")
+ }
+ })
+
+ t.Run("SaveSearchWithError", func(t *testing.T) {
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "Failed search",
+ Source: "web",
+ Error: "API rate limit exceeded",
+ Duration: 10,
+ }
+
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 1 {
+ t.Fatalf("Expected 1 search, got %d", len(searches))
+ }
+
+ if searches[0].Error != "API rate limit exceeded" {
+ t.Errorf("Expected error 'API rate limit exceeded', got '%s'", searches[0].Error)
+ }
+ })
+
+ t.Run("SaveSearchWithoutRequestID", func(t *testing.T) {
+ search := &types.Search{
+ ChatID: chat.ChatID,
+ Query: "Test",
+ Source: "web",
+ }
+
+ err := store.SaveSearch(search)
+ if err == nil {
+ t.Error("Expected error when saving without request_id")
+ }
+ })
+
+ t.Run("SaveSearchWithoutChatID", func(t *testing.T) {
+ search := &types.Search{
+ RequestID: "req_test",
+ Query: "Test",
+ Source: "web",
+ }
+
+ err := store.SaveSearch(search)
+ if err == nil {
+ t.Error("Expected error when saving without chat_id")
+ }
+ })
+
+ t.Run("SaveSearchWithoutSource", func(t *testing.T) {
+ search := &types.Search{
+ RequestID: "req_test",
+ ChatID: chat.ChatID,
+ Query: "Test",
+ }
+
+ err := store.SaveSearch(search)
+ if err == nil {
+ t.Error("Expected error when saving without source")
+ }
+ })
+
+ t.Run("SaveNilSearch", func(t *testing.T) {
+ err := store.SaveSearch(nil)
+ if err == nil {
+ t.Error("Expected error when saving nil search")
+ }
+ })
+}
+
+// TestGetSearches tests retrieving search records
+func TestGetSearches(t *testing.T) {
+ test.Prepare(t, config.Conf)
+ defer test.Clean()
+
+ store, err := xun.NewXun(types.Setting{
+ Connector: "default",
+ })
+ if err != nil {
+ t.Fatalf("Failed to create store: %v", err)
+ }
+
+ // Create a chat
+ chat := &types.Chat{
+ AssistantID: "test_assistant",
+ }
+ err = store.CreateChat(chat)
+ if err != nil {
+ t.Fatalf("Failed to create chat: %v", err)
+ }
+ defer store.DeleteChat(chat.ChatID)
+
+ t.Run("GetMultipleSearches", func(t *testing.T) {
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+
+ // Save multiple searches for the same request
+ for i := 1; i <= 3; i++ {
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: fmt.Sprintf("Query %d", i),
+ Source: "web",
+ Duration: int64(i * 100),
+ }
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search %d: %v", i, err)
+ }
+ time.Sleep(10 * time.Millisecond) // Ensure different created_at
+ }
+
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 3 {
+ t.Errorf("Expected 3 searches, got %d", len(searches))
+ }
+
+ // Verify order (by created_at asc)
+ for i := 0; i < len(searches)-1; i++ {
+ if searches[i].CreatedAt.After(searches[i+1].CreatedAt) {
+ t.Error("Searches not ordered by created_at asc")
+ }
+ }
+ })
+
+ t.Run("GetSearchesForNonExistentRequest", func(t *testing.T) {
+ searches, err := store.GetSearches("nonexistent_request")
+ if err != nil {
+ t.Fatalf("Unexpected error: %v", err)
+ }
+ if len(searches) != 0 {
+ t.Errorf("Expected 0 searches, got %d", len(searches))
+ }
+ })
+
+ t.Run("GetSearchesWithEmptyRequestID", func(t *testing.T) {
+ _, err := store.GetSearches("")
+ if err == nil {
+ t.Error("Expected error when getting searches without request_id")
+ }
+ })
+}
+
+// TestGetReference tests retrieving a single reference
+func TestGetReference(t *testing.T) {
+ test.Prepare(t, config.Conf)
+ defer test.Clean()
+
+ store, err := xun.NewXun(types.Setting{
+ Connector: "default",
+ })
+ if err != nil {
+ t.Fatalf("Failed to create store: %v", err)
+ }
+
+ // Create a chat
+ chat := &types.Chat{
+ AssistantID: "test_assistant",
+ }
+ err = store.CreateChat(chat)
+ if err != nil {
+ t.Fatalf("Failed to create chat: %v", err)
+ }
+ defer store.DeleteChat(chat.ChatID)
+
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+
+ // Save search with references
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "Test query",
+ Source: "web",
+ References: []types.Reference{
+ {Index: 1, Type: "web", Title: "Reference 1", URL: "https://example.com/1"},
+ {Index: 2, Type: "web", Title: "Reference 2", URL: "https://example.com/2"},
+ {Index: 3, Type: "kb", Title: "Reference 3", Content: "KB content"},
+ },
+ Duration: 100,
+ }
+ err = store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ t.Run("GetExistingReference", func(t *testing.T) {
+ ref, err := store.GetReference(requestID, 1)
+ if err != nil {
+ t.Fatalf("Failed to get reference: %v", err)
+ }
+
+ if ref.Title != "Reference 1" {
+ t.Errorf("Expected title 'Reference 1', got '%s'", ref.Title)
+ }
+ if ref.URL != "https://example.com/1" {
+ t.Errorf("Expected URL 'https://example.com/1', got '%s'", ref.URL)
+ }
+ })
+
+ t.Run("GetReferenceByIndex", func(t *testing.T) {
+ ref, err := store.GetReference(requestID, 3)
+ if err != nil {
+ t.Fatalf("Failed to get reference: %v", err)
+ }
+
+ if ref.Type != "kb" {
+ t.Errorf("Expected type 'kb', got '%s'", ref.Type)
+ }
+ if ref.Content != "KB content" {
+ t.Errorf("Expected content 'KB content', got '%s'", ref.Content)
+ }
+ })
+
+ t.Run("GetNonExistentReference", func(t *testing.T) {
+ _, err := store.GetReference(requestID, 999)
+ if err == nil {
+ t.Error("Expected error when getting non-existent reference")
+ }
+ })
+
+ t.Run("GetReferenceWithInvalidIndex", func(t *testing.T) {
+ _, err := store.GetReference(requestID, 0)
+ if err == nil {
+ t.Error("Expected error when getting reference with index 0")
+ }
+
+ _, err = store.GetReference(requestID, -1)
+ if err == nil {
+ t.Error("Expected error when getting reference with negative index")
+ }
+ })
+
+ t.Run("GetReferenceWithEmptyRequestID", func(t *testing.T) {
+ _, err := store.GetReference("", 1)
+ if err == nil {
+ t.Error("Expected error when getting reference without request_id")
+ }
+ })
+}
+
+// TestDeleteSearches tests deleting search records
+func TestDeleteSearches(t *testing.T) {
+ test.Prepare(t, config.Conf)
+ defer test.Clean()
+
+ store, err := xun.NewXun(types.Setting{
+ Connector: "default",
+ })
+ if err != nil {
+ t.Fatalf("Failed to create store: %v", err)
+ }
+
+ t.Run("DeleteSearchesForChat", func(t *testing.T) {
+ // Create a chat
+ chat := &types.Chat{
+ AssistantID: "test_assistant",
+ }
+ err := store.CreateChat(chat)
+ if err != nil {
+ t.Fatalf("Failed to create chat: %v", err)
+ }
+ defer store.DeleteChat(chat.ChatID)
+
+ // Save multiple searches
+ for i := 1; i <= 3; i++ {
+ requestID := fmt.Sprintf("req_%d_%d", time.Now().UnixNano(), i)
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: fmt.Sprintf("Query %d", i),
+ Source: "web",
+ Duration: 100,
+ }
+ err := store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+ }
+
+ // Delete all searches for the chat
+ err = store.DeleteSearches(chat.ChatID)
+ if err != nil {
+ t.Fatalf("Failed to delete searches: %v", err)
+ }
+
+ // Note: GetSearches filters by request_id, not chat_id
+ // We can't easily verify deletion without a GetSearchesByChatID method
+ // But the soft delete should have been applied
+ })
+
+ t.Run("DeleteSearchesWithEmptyChatID", func(t *testing.T) {
+ err := store.DeleteSearches("")
+ if err == nil {
+ t.Error("Expected error when deleting searches without chat_id")
+ }
+ })
+}
+
+// TestSearchCompleteWorkflow tests a complete search workflow
+func TestSearchCompleteWorkflow(t *testing.T) {
+ test.Prepare(t, config.Conf)
+ defer test.Clean()
+
+ store, err := xun.NewXun(types.Setting{
+ Connector: "default",
+ })
+ if err != nil {
+ t.Fatalf("Failed to create store: %v", err)
+ }
+
+ t.Run("CompleteWorkflow", func(t *testing.T) {
+ // 1. Create chat
+ chat := &types.Chat{
+ AssistantID: "workflow_assistant",
+ Title: "Search Workflow Test",
+ }
+ err := store.CreateChat(chat)
+ if err != nil {
+ t.Fatalf("Failed to create chat: %v", err)
+ }
+ defer store.DeleteChat(chat.ChatID)
+
+ requestID := fmt.Sprintf("req_%d", time.Now().UnixNano())
+
+ // 2. Save search with full data
+ search := &types.Search{
+ RequestID: requestID,
+ ChatID: chat.ChatID,
+ Query: "What are the best practices for Go programming?",
+ Config: map[string]any{
+ "uses": map[string]any{"search": "builtin", "web": "builtin"},
+ "web": map[string]any{"provider": "tavily", "max_results": 5},
+ },
+ Keywords: []string{"Go", "programming", "best practices"},
+ Source: "auto",
+ References: []types.Reference{
+ {Index: 1, Type: "web", Title: "Effective Go", URL: "https://go.dev/doc/effective_go"},
+ {Index: 2, Type: "web", Title: "Go Proverbs", URL: "https://go-proverbs.github.io/"},
+ {Index: 3, Type: "kb", Title: "Internal Go Guide", Content: "Our team's Go coding standards..."},
+ },
+ XML: "[...]",
+ Prompt: "When citing, use [1], [2], [3] format.",
+ Duration: 350,
+ }
+
+ err = store.SaveSearch(search)
+ if err != nil {
+ t.Fatalf("Failed to save search: %v", err)
+ }
+
+ // 3. Retrieve searches
+ searches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches: %v", err)
+ }
+
+ if len(searches) != 1 {
+ t.Fatalf("Expected 1 search, got %d", len(searches))
+ }
+
+ // 4. Verify all fields
+ s := searches[0]
+ if s.Query != "What are the best practices for Go programming?" {
+ t.Errorf("Query mismatch")
+ }
+ if len(s.Keywords) != 3 {
+ t.Errorf("Expected 3 keywords, got %d", len(s.Keywords))
+ }
+ if len(s.References) != 3 {
+ t.Errorf("Expected 3 references, got %d", len(s.References))
+ }
+ if s.Config == nil {
+ t.Error("Config should not be nil")
+ }
+
+ // 5. Get specific reference
+ ref, err := store.GetReference(requestID, 2)
+ if err != nil {
+ t.Fatalf("Failed to get reference: %v", err)
+ }
+ if ref.Title != "Go Proverbs" {
+ t.Errorf("Expected 'Go Proverbs', got '%s'", ref.Title)
+ }
+
+ // 6. Delete searches
+ err = store.DeleteSearches(chat.ChatID)
+ if err != nil {
+ t.Fatalf("Failed to delete searches: %v", err)
+ }
+
+ // 7. Verify deletion (soft delete, so GetSearches should return empty)
+ deletedSearches, err := store.GetSearches(requestID)
+ if err != nil {
+ t.Fatalf("Failed to get searches after delete: %v", err)
+ }
+ if len(deletedSearches) != 0 {
+ t.Errorf("Expected 0 searches after delete, got %d", len(deletedSearches))
+ }
+
+ t.Log("Complete search workflow passed!")
+ })
+}
diff --git a/data/bindata.go b/data/bindata.go
index c6f04a69..e2f8a6d7 100644
--- a/data/bindata.go
+++ b/data/bindata.go
@@ -114,6 +114,7 @@
// .tmp/data/yao/models/agent/chat.mod.yao
// .tmp/data/yao/models/agent/message.mod.yao
// .tmp/data/yao/models/agent/resume.mod.yao
+// .tmp/data/yao/models/agent/search.mod.yao
// .tmp/data/yao/models/attachment.mod.yao
// .tmp/data/yao/models/audit.mod.yao
// .tmp/data/yao/models/config.mod.yao
@@ -320,7 +321,7 @@ func cuiSetupIndexHtml() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "cui/setup/index.html", size: 10, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "cui/setup/index.html", size: 10, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -340,7 +341,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(1765593352, 0)}
+ info := bindataFileInfo{name: "cui/v0.9/index.html", size: 13, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -360,7 +361,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(1765593352, 0)}
+ info := bindataFileInfo{name: "cui/v1.0/index.html", size: 49, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -380,7 +381,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(1765593352, 0)}
+ info := bindataFileInfo{name: "cui/v1.0/layouts__index.async.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -400,7 +401,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(1765593352, 0)}
+ info := bindataFileInfo{name: "cui/v1.0/umi.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -420,7 +421,7 @@ func initEnv() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/.env", size: 219, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.env", size: 219, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -440,7 +441,7 @@ func initVscodeSettingsJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/.vscode/settings.json", size: 4666, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/settings.json", size: 4666, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -460,7 +461,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/console.d.ts", size: 221, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -480,7 +481,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/exception.d.ts", size: 738, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -500,7 +501,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/fs.d.ts", size: 8554, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -520,7 +521,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/global.d.ts", size: 1759, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -540,7 +541,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/http.d.ts", size: 6179, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -560,7 +561,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/io.d.ts", size: 587, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -580,7 +581,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/log.d.ts", size: 1692, mode: os.FileMode(493), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -600,7 +601,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/neo.d.ts", size: 3750, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -620,7 +621,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/process/fs.d.ts", size: 11133, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -640,7 +641,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/process/http.d.ts", size: 5653, mode: os.FileMode(493), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -660,7 +661,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/process/model.d.ts", size: 6656, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -680,7 +681,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/process.d.ts", size: 23165, mode: os.FileMode(493), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -700,7 +701,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/query.d.ts", size: 6124, mode: os.FileMode(493), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -720,7 +721,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/store.d.ts", size: 2251, mode: os.FileMode(493), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -740,7 +741,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/sui.d.ts", size: 1713, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -760,7 +761,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime/time.d.ts", size: 711, mode: os.FileMode(493), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -780,7 +781,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/runtime.d.ts", size: 424, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -800,7 +801,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/.vscode/types/sui.d.ts", size: 8931, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -820,7 +821,7 @@ func initAppYao() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/app.yao", size: 3115, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/app.yao", size: 3115, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -840,7 +841,7 @@ func initDataReadmeMd() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/data/README.md", size: 41, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/README.md", size: 41, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -860,7 +861,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/__assets/README.md", size: 33, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -880,7 +881,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/__assets/images/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -900,7 +901,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/__assets/images/logos/logo_color.svg", size: 2909, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -920,7 +921,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/__assets/images/logos/wordmark.svg", size: 3615, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -940,7 +941,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/__data.json", size: 30, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -960,7 +961,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/__document.html", size: 492, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -980,7 +981,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/index/index.css", size: 2896, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1000,7 +1001,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/index/index.html", size: 2361, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1020,7 +1021,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/data/templates/default/index/index.json", size: 31, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1040,7 +1041,7 @@ func initDbReadmeMd() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/db/README.md", size: 84, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/db/README.md", size: 84, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1060,7 +1061,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/flows/menu.flow.yao", size: 813, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1080,7 +1081,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/forms/account.form.yao", size: 1194, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1100,7 +1101,7 @@ func initIconsAppIcns() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/icons/app.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/icons/app.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1120,7 +1121,7 @@ func initIconsAppIco() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/icons/app.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/icons/app.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1140,7 +1141,7 @@ func initIconsAppPng() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1160,7 +1161,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/logins/admin.login.yao", size: 302, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1180,7 +1181,7 @@ func initLogsReadmeMd() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/logs/README.md", size: 28, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/logs/README.md", size: 28, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1200,7 +1201,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/models/admin/user.mod.yao", size: 6416, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1220,7 +1221,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/models/tests/pet.mod.yao", size: 525, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1240,7 +1241,7 @@ func initNeoNeoYml() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/neo/neo.yml", size: 724, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/neo/neo.yml", size: 724, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1260,7 +1261,7 @@ func initPublicReadmeMd() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/public/README.md", size: 108, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/README.md", size: 108, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1280,7 +1281,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/assets/README.md", size: 33, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1300,7 +1301,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/assets/images/icons/app.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1320,7 +1321,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/assets/images/logos/logo_color.svg", size: 2909, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1340,7 +1341,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/assets/images/logos/wordmark.svg", size: 3615, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1360,7 +1361,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/assets/libsui.min.js", size: 12569, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1380,7 +1381,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/assets/libsui.min.js.map", size: 38553, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1400,7 +1401,7 @@ func initPublicIndexCfg() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/public/index.cfg", size: 85, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/index.cfg", size: 85, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1420,7 +1421,7 @@ func initPublicIndexSui() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/public/index.sui", size: 5682, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/public/index.sui", size: 5682, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1440,7 +1441,7 @@ func initScriptsAccountTs() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/scripts/account.ts", size: 2521, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/scripts/account.ts", size: 2521, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1460,7 +1461,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/scripts/ai/neo.ts", size: 375, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1480,7 +1481,7 @@ func initScriptsTestsTs() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/scripts/tests.ts", size: 1044, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/scripts/tests.ts", size: 1044, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1500,7 +1501,7 @@ func initScriptsUtilsTs() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/scripts/utils.ts", size: 1230, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/scripts/utils.ts", size: 1230, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1520,7 +1521,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/suis/web.sui.yao", size: 675, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1540,7 +1541,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(1765593352, 0)}
+ info := bindataFileInfo{name: "init/tables/account.tab.yao", size: 5597, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1560,7 +1561,7 @@ func initTsconfigJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "init/tsconfig.json", size: 178, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "init/tsconfig.json", size: 178, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1580,7 +1581,7 @@ func libsuiAgentTs() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "libsui/agent.ts", size: 15267, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "libsui/agent.ts", size: 15267, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1600,7 +1601,7 @@ func libsuiIndexTs() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "libsui/index.ts", size: 13049, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "libsui/index.ts", size: 13049, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1620,7 +1621,7 @@ func libsuiUtilsTs() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "libsui/utils.ts", size: 5959, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "libsui/utils.ts", size: 5959, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1640,7 +1641,7 @@ func libsuiYaoTs() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "libsui/yao.ts", size: 4338, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "libsui/yao.ts", size: 4338, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1660,7 +1661,7 @@ func publicIndexHtml() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "public/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "public/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1680,7 +1681,7 @@ func uiIndexHtml() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "ui/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "ui/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1700,7 +1701,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1720,7 +1721,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1740,7 +1741,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1760,7 +1761,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1780,7 +1781,7 @@ func yaoDataIndexHtml() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1800,7 +1801,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/chunking/semantic/en.json", size: 5543, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1820,7 +1821,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/chunking/semantic/zh-cn.json", size: 5446, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1840,7 +1841,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/chunking/structured/en.json", size: 2423, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1860,7 +1861,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/chunking/structured/zh-cn.json", size: 2321, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1880,7 +1881,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/mcp/en.json", size: 4235, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1900,7 +1901,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/mcp/zh-cn.json", size: 4060, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1920,7 +1921,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/ocr/en.json", size: 6631, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1940,7 +1941,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/ocr/zh-cn.json", size: 6501, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1960,7 +1961,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/office/en.json", size: 5476, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -1980,7 +1981,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/office/zh-cn.json", size: 5356, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2000,7 +2001,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/utf8/en.json", size: 292, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2020,7 +2021,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/utf8/zh-cn.json", size: 281, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2040,7 +2041,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/video/en.json", size: 6411, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2060,7 +2061,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/video/zh-cn.json", size: 6297, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2080,7 +2081,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/vision/en.json", size: 4085, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2100,7 +2101,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/vision/zh-cn.json", size: 3949, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2120,7 +2121,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/whisper/en.json", size: 4449, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2140,7 +2141,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/converter/whisper/zh-cn.json", size: 4312, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2160,7 +2161,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/embedding/fastembed/en.json", size: 6865, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2180,7 +2181,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/embedding/fastembed/zh-cn.json", size: 6685, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2200,7 +2201,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/embedding/openai/en.json", size: 5636, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2220,7 +2221,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/embedding/openai/zh-cn.json", size: 5463, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2240,7 +2241,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/extraction/openai/en.json", size: 9110, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2260,7 +2261,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/extraction/openai/zh-cn.json", size: 8827, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2280,7 +2281,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/http/en.json", size: 5885, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2300,7 +2301,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/http/zh-cn.json", size: 5925, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2320,7 +2321,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/mcp/en.json", size: 6819, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2340,7 +2341,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/data/kb/providers/fetcher/mcp/zh-cn.json", size: 6611, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2360,7 +2361,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/fields/model.trans.json", size: 14938, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2380,7 +2381,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2400,7 +2401,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/langs/zh-cn/global.yml", size: 1762, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2420,7 +2421,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/langs/zh-cn/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2440,7 +2441,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/langs/zh-cn/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2460,7 +2461,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/langs/zh-hk/global.yml", size: 1762, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2480,7 +2481,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/langs/zh-hk/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2500,7 +2501,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/langs/zh-hk/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2520,7 +2521,7 @@ func yaoModelsAgentAssistantModYao() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "yao/models/agent/assistant.mod.yao", size: 6945, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/agent/assistant.mod.yao", size: 6945, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2540,7 +2541,7 @@ func yaoModelsAgentChatModYao() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "yao/models/agent/chat.mod.yao", size: 3093, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/agent/chat.mod.yao", size: 3093, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2560,7 +2561,7 @@ func yaoModelsAgentMessageModYao() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "yao/models/agent/message.mod.yao", size: 3712, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/agent/message.mod.yao", size: 3712, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2580,7 +2581,27 @@ 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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/agent/resume.mod.yao", size: 3896, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _yaoModelsAgentSearchModYao = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x96\xcd\x6e\xe3\x36\x10\x80\xef\x7e\x8a\x81\x4e\x5b\x20\xdd\x00\x6d\x51\xc0\xbe\xb5\xeb\x34\x28\xea\xec\x6e\xe3\xcb\x02\x41\x60\x50\xe2\x48\x66\x4d\x91\xca\x90\x82\x2d\x18\x7e\xf7\x82\xd4\x4f\x68\x49\x69\x64\xb7\xbd\x18\xd6\xfc\xf1\x9b\x21\x67\x30\xc7\x19\x40\xa4\x58\x8e\xd1\x02\xa2\x35\x32\x4a\xb6\xd1\x8d\x93\x49\x16\xa3\xec\x0b\x39\x9a\x84\x44\x61\x85\x56\xaf\x2a\x20\x4c\x34\x71\x03\xa9\x26\x48\x84\x65\x4e\x0d\xa6\x2c\x0a\x4d\x16\x98\xe2\xc0\x31\x2e\xb3\x4c\xa8\xac\x8e\x62\x59\x66\xa2\x05\x3c\x45\x2c\x43\x65\xa3\x1b\x88\x4c\x65\x2c\xe6\xd1\xb3\x57\xc7\xa5\x90\x56\xb8\x03\x2c\x95\xe8\x45\x84\x8c\x6b\x25\xab\x50\x66\x34\xd9\x68\x01\xf3\xf9\x7c\xde\x44\x8d\xa5\xcb\xe2\xf8\x9a\x8f\x8f\xbf\x31\x4d\x02\x10\x25\x3a\xcf\xdd\x89\x0b\x88\x7e\x71\x2a\xa8\x55\x50\xbb\xc2\xc9\xc7\x49\xb4\x2c\x73\xe5\x01\x67\x00\x00\x47\xff\x1b\x54\x49\x70\x9f\x86\x97\xd9\xaa\xf0\xb2\xdf\x97\xaf\xb2\xae\x72\xa1\x30\x3c\xba\xb4\xfa\x7b\xa1\x12\x42\x27\x81\x82\x44\xce\xa8\x82\x1d\x56\x91\xb7\x3e\xdd\x8c\x9f\x4b\xf8\x52\xa2\xb1\x9b\xb1\xf3\x8d\xa5\xb6\xbc\xe7\x0c\x8f\xb5\x13\xbc\xc5\x62\x8c\x4e\x04\xb3\xc8\x81\x46\x2c\x25\xaa\xcc\x6e\xa3\x05\xfc\xfc\x53\x27\x53\xa5\x94\x4d\xa9\x53\x26\x0d\x76\x0a\xa1\x38\x1e\x9a\x1b\xfa\xc7\x44\x92\x2d\xbb\x30\x8b\x4f\x5b\x36\x25\x85\xa4\x6f\xf6\xff\xf0\xbf\x94\x48\xd5\x90\xde\xe2\xc1\x8e\xb0\xff\x79\x6e\x1d\x90\x7f\x21\x91\x09\xc5\x64\xfb\x0c\x7b\x71\x03\xd0\xf7\x4b\xaa\x55\x2a\xb2\x21\xd3\x5f\x46\xab\xb1\x7a\xf6\xcc\x03\xa8\xa6\xa7\xeb\x80\x50\x1a\xe4\xf0\xc1\x35\xb6\x2d\x95\x50\xd9\x77\xd7\xe1\xed\xb0\xda\xbb\x11\x31\x19\xf0\x8f\x81\x43\x80\x78\x77\xb0\xc4\x12\x77\xe1\x6d\x5c\xf8\x90\x92\xce\xe1\xf3\xea\xeb\x95\x80\xa8\xac\xb0\x02\xa7\x03\xde\x0d\x1c\x46\x01\xdb\xb8\x75\x0d\xef\x89\x15\xdb\xe6\xb6\xaf\x04\x25\x94\x7e\xbe\x4e\x27\x7d\x1c\x7a\x8c\xa2\x76\x91\xff\x33\x56\x6e\xe4\x64\xca\xe5\x7a\x35\xca\x77\x8f\x0a\xc9\x37\xb7\xef\xa3\xe5\x7a\x55\xe3\x2d\x7f\xfd\x77\x6c\x46\x97\x94\xe0\x05\x23\x68\xdd\x73\x18\xb6\x4c\x1d\x72\x01\x7b\x8c\x6f\x77\xf1\x2d\x8f\x6f\x59\x69\xf5\xc8\x30\xfa\xf1\x87\x37\x87\xd1\x3b\x77\x9f\x22\xa1\x4a\x2e\x78\xa6\x8f\x23\x2e\x01\x79\xa7\x7e\x7a\x86\xbd\xb0\x5b\xc8\xa4\x8e\x99\x84\x7a\x14\x5e\x55\xd8\xcc\xbd\x9b\xc9\x7c\xf7\xe7\xd6\xe1\xc5\x3b\xcd\x67\xcd\x1d\x9a\x6f\xee\x9d\xd2\x7b\x89\x3c\x43\xe8\x1d\x71\x09\xdd\x21\x1f\x79\x92\x6f\x0c\xee\x6f\x0f\xe3\x4f\xf2\x37\x4d\x39\xb3\xee\x49\x7e\x7b\x58\xf9\xa5\x67\xb5\x7a\x70\x03\xf3\x3c\xce\x25\x58\x05\xe9\xbc\xb0\x93\xc9\xbe\xf6\xcc\x03\xb8\x4f\xed\xfe\x25\x94\xb1\x54\x26\xfe\x7f\x3f\xfc\x45\x4d\x5c\x92\x0f\x38\x84\x13\xca\x62\x86\x34\xd6\xcc\x03\x9f\x61\xb7\xb4\x71\x41\x28\xc8\x85\x94\xc2\x60\xa2\x55\x38\xf1\x2f\x9a\xdf\x44\x9a\x26\xd7\xef\xee\xdc\x3a\x1c\x87\x4e\x03\x39\x1a\xc3\x32\x04\x91\x42\xca\x84\x44\xfe\x0e\xd4\x0c\xe0\xb9\xd9\x53\xdb\x59\xbb\x68\x18\xfd\xb2\xd3\x7d\x05\x68\x5b\x66\xbe\xa8\x60\x9e\xe4\x9a\xd7\x70\x9b\x4d\xc5\xf4\x47\xbf\xba\x7e\xf4\xce\x9d\x89\xdb\x10\xc7\xd6\xa7\x54\x13\x8a\x4c\x85\xba\x8e\xab\xde\x69\x75\xbb\xb2\x1f\x21\xb2\x22\x47\x63\x59\x5e\x98\x76\x9b\x76\xd3\x30\xb5\x1b\x8e\x12\x2d\xb6\x52\x38\xcd\x4e\xb3\xd9\xdf\x01\x00\x00\xff\xff\x6a\x0f\xca\x67\x1f\x0c\x00\x00")
+
+func yaoModelsAgentSearchModYaoBytes() ([]byte, error) {
+ return bindataRead(
+ _yaoModelsAgentSearchModYao,
+ "yao/models/agent/search.mod.yao",
+ )
+}
+
+func yaoModelsAgentSearchModYao() (*asset, error) {
+ bytes, err := yaoModelsAgentSearchModYaoBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "yao/models/agent/search.mod.yao", size: 3103, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2600,7 +2621,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/attachment.mod.yao", size: 4687, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2620,7 +2641,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/audit.mod.yao", size: 5588, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2640,7 +2661,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/config.mod.yao", size: 1649, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2660,7 +2681,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/dsl.mod.yao", size: 3826, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2680,7 +2701,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/invitation.mod.yao", size: 6693, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2700,7 +2721,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/job/category.mod.yao", size: 2041, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2720,7 +2741,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/job/execution.mod.yao", size: 7201, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2740,7 +2761,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/job/job.mod.yao", size: 6330, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2760,7 +2781,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/job/log.mod.yao", size: 4711, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2780,7 +2801,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/kb/collection.mod.yao", size: 5390, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2800,7 +2821,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/kb/document.mod.yao", size: 9906, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2820,7 +2841,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/member.mod.yao", size: 14798, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2840,7 +2861,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/role.mod.yao", size: 6434, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2860,7 +2881,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/team.mod.yao", size: 15823, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2880,7 +2901,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/user/oauth_account.mod.yao", size: 6928, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2900,7 +2921,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/user/type.mod.yao", size: 7502, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2920,7 +2941,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/models/user.mod.yao", size: 12335, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2940,7 +2961,7 @@ func yaoReleaseAppYaz() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "yao/release/app.yaz", size: 181682, mode: os.FileMode(420), modTime: time.Unix(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/release/app.yaz", size: 181682, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2960,7 +2981,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/agent/cache.lru.yao", size: 301, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -2980,7 +3001,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/agent/memory.badger.yao", size: 352, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3000,7 +3021,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/cache.lru.yao", size: 285, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3020,7 +3041,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/kb/cache.lru.yao", size: 304, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3040,7 +3061,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/kb/store.badger.yao", size: 349, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3060,7 +3081,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/oauth/cache.lru.yao", size: 301, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3080,7 +3101,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/oauth/client.badger.yao", size: 352, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3100,7 +3121,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/oauth/store.badger.yao", size: 376, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3120,7 +3141,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/stores/store.badger.yao", size: 341, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3140,7 +3161,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(1765593352, 0)}
+ info := bindataFileInfo{name: "yao/uploaders/attachment.local.yao", size: 1163, mode: os.FileMode(420), modTime: time.Unix(1765784079, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -3311,6 +3332,7 @@ var _bindata = map[string]func() (*asset, error){
"yao/models/agent/chat.mod.yao": yaoModelsAgentChatModYao,
"yao/models/agent/message.mod.yao": yaoModelsAgentMessageModYao,
"yao/models/agent/resume.mod.yao": yaoModelsAgentResumeModYao,
+ "yao/models/agent/search.mod.yao": yaoModelsAgentSearchModYao,
"yao/models/attachment.mod.yao": yaoModelsAttachmentModYao,
"yao/models/audit.mod.yao": yaoModelsAuditModYao,
"yao/models/config.mod.yao": yaoModelsConfigModYao,
@@ -3637,6 +3659,7 @@ var _bintree = &bintree{nil, map[string]*bintree{
"chat.mod.yao": {yaoModelsAgentChatModYao, map[string]*bintree{}},
"message.mod.yao": {yaoModelsAgentMessageModYao, map[string]*bintree{}},
"resume.mod.yao": {yaoModelsAgentResumeModYao, map[string]*bintree{}},
+ "search.mod.yao": {yaoModelsAgentSearchModYao, map[string]*bintree{}},
}},
"attachment.mod.yao": {yaoModelsAttachmentModYao, map[string]*bintree{}},
"audit.mod.yao": {yaoModelsAuditModYao, map[string]*bintree{}},
diff --git a/model/model.go b/model/model.go
index 3b34eddc..45f88fa1 100644
--- a/model/model.go
+++ b/model/model.go
@@ -24,6 +24,7 @@ var systemModels = map[string]string{
"__yao.agent.chat": "yao/models/agent/chat.mod.yao",
"__yao.agent.message": "yao/models/agent/message.mod.yao",
"__yao.agent.resume": "yao/models/agent/resume.mod.yao",
+ "__yao.agent.search": "yao/models/agent/search.mod.yao",
"__yao.attachment": "yao/models/attachment.mod.yao",
"__yao.audit": "yao/models/audit.mod.yao",
"__yao.config": "yao/models/config.mod.yao",
diff --git a/test/utils.go b/test/utils.go
index 57c26135..6066bbbd 100644
--- a/test/utils.go
+++ b/test/utils.go
@@ -199,6 +199,7 @@ var testSystemModels = map[string]string{
"__yao.agent.chat": "yao/models/agent/chat.mod.yao",
"__yao.agent.message": "yao/models/agent/message.mod.yao",
"__yao.agent.resume": "yao/models/agent/resume.mod.yao",
+ "__yao.agent.search": "yao/models/agent/search.mod.yao",
"__yao.attachment": "yao/models/attachment.mod.yao",
"__yao.audit": "yao/models/audit.mod.yao",
"__yao.config": "yao/models/config.mod.yao",
diff --git a/yao/models/agent/search.mod.yao b/yao/models/agent/search.mod.yao
new file mode 100644
index 00000000..f253ace5
--- /dev/null
+++ b/yao/models/agent/search.mod.yao
@@ -0,0 +1,138 @@
+{
+ "name": "Search",
+ "label": "Search",
+ "description": "Search records for citation support and debugging",
+ "tags": ["agent", "system"],
+ "builtin": true,
+ "readonly": true,
+ "sort": 9999,
+ "table": { "name": "agent_search", "comment": "Agent search table" },
+ "columns": [
+ {
+ "name": "id",
+ "type": "ID",
+ "label": "ID",
+ "comment": "Auto-increment primary key"
+ },
+ {
+ "name": "request_id",
+ "type": "string",
+ "label": "Request ID",
+ "comment": "Associated request ID",
+ "length": 64,
+ "nullable": false,
+ "index": true
+ },
+ {
+ "name": "chat_id",
+ "type": "string",
+ "label": "Chat ID",
+ "comment": "Associated chat ID",
+ "length": 64,
+ "nullable": false,
+ "index": true
+ },
+ {
+ "name": "query",
+ "type": "text",
+ "label": "Query",
+ "comment": "Original search query",
+ "nullable": true
+ },
+ {
+ "name": "config",
+ "type": "json",
+ "label": "Config",
+ "comment": "Search config used (for tuning)",
+ "nullable": true
+ },
+ {
+ "name": "keywords",
+ "type": "json",
+ "label": "Keywords",
+ "comment": "Extracted keywords (from NLP)",
+ "nullable": true
+ },
+ {
+ "name": "entities",
+ "type": "json",
+ "label": "Entities",
+ "comment": "Extracted entities (for Graph search)",
+ "nullable": true
+ },
+ {
+ "name": "relations",
+ "type": "json",
+ "label": "Relations",
+ "comment": "Extracted relations (for Graph search)",
+ "nullable": true
+ },
+ {
+ "name": "dsl",
+ "type": "json",
+ "label": "DSL",
+ "comment": "Generated QueryDSL (for DB search)",
+ "nullable": true
+ },
+ {
+ "name": "source",
+ "type": "string",
+ "label": "Source",
+ "comment": "Search source: web/kb/db/auto",
+ "length": 32,
+ "nullable": false
+ },
+ {
+ "name": "references",
+ "type": "json",
+ "label": "References",
+ "comment": "Reference[] with global index",
+ "nullable": true
+ },
+ {
+ "name": "graph",
+ "type": "json",
+ "label": "Graph",
+ "comment": "GraphNode[] from knowledge graph",
+ "nullable": true
+ },
+ {
+ "name": "xml",
+ "type": "text",
+ "label": "XML",
+ "comment": "Formatted XML for LLM context",
+ "nullable": true
+ },
+ {
+ "name": "prompt",
+ "type": "text",
+ "label": "Prompt",
+ "comment": "Citation instruction prompt",
+ "nullable": true
+ },
+ {
+ "name": "duration",
+ "type": "integer",
+ "label": "Duration",
+ "comment": "Search duration in milliseconds",
+ "nullable": true
+ },
+ {
+ "name": "error",
+ "type": "text",
+ "label": "Error",
+ "comment": "Error message if failed",
+ "nullable": true
+ }
+ ],
+ "relations": {
+ "chat": {
+ "type": "hasOne",
+ "model": "__yao.agent.chat",
+ "key": "chat_id",
+ "foreign": "chat_id"
+ }
+ },
+ "option": { "timestamps": true, "soft_deletes": true }
+}
+