package cli import ( "fmt" "strconv" "strings" ) // Command parsers func (p *Parser) parseLogout() (*Command, error) { cmd := NewCommand("logout") p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseLoginUser() (*Command, error) { cmd := NewCommand("login_user") p.nextToken() // consume LOGIN if p.curToken.Type != TokenUser { return nil, fmt.Errorf("expected USER after LOGIN") } p.nextToken() email, err := p.parseQuotedString() if err != nil { return nil, err } cmd.Params["email"] = email p.nextToken() // Optional: PASSWORD 'password' if p.curToken.Type == TokenPassword { p.nextToken() password, err := p.parseQuotedString() if err != nil { return nil, err } cmd.Params["password"] = password p.nextToken() } // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parsePingServer() (*Command, error) { cmd := NewCommand("ping") p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseRegisterCommand() (*Command, error) { cmd := NewCommand("register_user") if err := p.expectPeek(TokenUser); err != nil { return nil, err } p.nextToken() // consume USER userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd.Params["user_name"] = userName p.nextToken() // consume Email if p.curToken.Type != TokenAs { return nil, fmt.Errorf("expected AS") } p.nextToken() // consume AS nickname, err := p.parseQuotedString() if err != nil { return nil, err } cmd.Params["nickname"] = nickname p.nextToken() // consume nickname if p.curToken.Type != TokenPassword { return nil, fmt.Errorf("expected PASSWORD") } p.nextToken() // consume PASSWORD password, err := p.parseQuotedString() if err != nil { return nil, err } cmd.Params["password"] = password p.nextToken() // consume 'password' // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseListCommand() (*Command, error) { p.nextToken() // consume LIST switch p.curToken.Type { case TokenVars: p.nextToken() // Semicolon is optional for SHOW TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("list_variables"), nil case TokenConfigs: p.nextToken() // Semicolon is optional for SHOW TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("list_configs"), nil case TokenEnvs: p.nextToken() // Semicolon is optional for SHOW TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("list_environments"), nil case TokenDatasets: return p.parseListDatasets() case TokenDocuments: return p.parseListDatasetDocuments() case TokenAgents: return p.parseListAgents() case TokenTokens: return p.parseListTokens() case TokenModel: return p.parseListModelProviders() case TokenSupported: return p.parseListModelsOfProvider() case TokenModels: return p.parseListModelsOfProvider() case TokenProviders: return p.parseListProviders() case TokenInstances: return p.parseListInstances() case TokenDefault: return p.parseListDefaultModels() case TokenAvailable: return p.parseCommonListProviders() case TokenChats: p.nextToken() // Semicolon is optional for SHOW TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("list_user_chats"), nil case TokenFiles: return p.parseListFiles() case TokenQuotedString: return p.parseListQuotedStringCommand() default: return nil, fmt.Errorf("unknown LIST target: %s", p.curToken.Value) } } func (p *Parser) parseListDatasets() (*Command, error) { cmd := NewCommand("list_datasets") p.nextToken() // consume DATASETS // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseListDatasetDocuments() (*Command, error) { p.nextToken() // consume DOCUMENTS if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() datasetID, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() cmd := NewCommand("list_dataset_documents") cmd.Params["dataset_id"] = datasetID // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseListAgents() (*Command, error) { p.nextToken() // consume AGENTS if p.curToken.Type == TokenSemicolon { return NewCommand("list_user_agents"), nil } if p.curToken.Type != TokenOf { return nil, fmt.Errorf("expected OF") } p.nextToken() userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("list_agents") cmd.Params["user_name"] = userName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseListTokens() (*Command, error) { p.nextToken() // consume TOKENS cmd := NewCommand("list_tokens") // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseListModelProviders() (*Command, error) { p.nextToken() // consume MODEL if p.curToken.Type != TokenProviders { return nil, fmt.Errorf("expected PROVIDERS") } p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("list_user_model_providers"), nil } // parseListProviders parses LIST PROVIDERS command func (p *Parser) parseListProviders() (*Command, error) { p.nextToken() // consume PROVIDERS // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("list_providers"), nil } func (p *Parser) parseListDefaultModels() (*Command, error) { p.nextToken() // consume DEFAULT if p.curToken.Type != TokenModels { return nil, fmt.Errorf("expected MODELS") } p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("list_user_default_models"), nil } func (p *Parser) parseListFiles() (*Command, error) { p.nextToken() // consume FILES if p.curToken.Type != TokenOf { return nil, fmt.Errorf("expected OF") } p.nextToken() if p.curToken.Type != TokenDataset { return nil, fmt.Errorf("expected DATASET") } p.nextToken() datasetName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("list_user_dataset_files") cmd.Params["dataset_name"] = datasetName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseListQuotedStringCommand() (*Command, error) { str, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() // consume str switch p.curToken.Type { case TokenTasks: p.nextToken() // consume TASKS cmd := NewCommand("list_tasks_user_command") cmd.Params["composite_instance_name"] = str return cmd, nil default: return nil, fmt.Errorf("unknown command: %s", str) } } func (p *Parser) parseShowQuotedStringCommand() (*Command, error) { str, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() // consume str switch p.curToken.Type { case TokenTask: p.nextToken() // consume TASK var taskID string taskID, err = p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected string: %w", err) } p.nextToken() cmd := NewCommand("show_task_user_command") cmd.Params["task_id"] = taskID cmd.Params["composite_instance_name"] = str p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil default: return nil, fmt.Errorf("unknown command: %s", str) } } func (p *Parser) parseShowCommand() (*Command, error) { p.nextToken() // consume SHOW switch p.curToken.Type { case TokenVersion: p.nextToken() // Semicolon is optional for SHOW TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("show_version"), nil case TokenToken: p.nextToken() // Semicolon is optional for SHOW TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("show_token"), nil case TokenCurrent: p.nextToken() if p.curToken.Type == TokenUser { p.nextToken() // Semicolon is optional for SHOW CURRENT USER if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("show_current_user"), nil } else if p.curToken.Type == TokenModel { p.nextToken() // Semicolon is optional for SHOW CURRENT MODEL if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("show_current_model"), nil } return nil, fmt.Errorf("expected USER or MODEL after CURRENT") case TokenUser: return p.parseShowUser() case TokenRole: return p.parseShowRole() case TokenVar: return p.parseShowVariable() case TokenService: return p.parseShowService() case TokenProvider: return p.parseShowProvider() case TokenModel: return p.parseShowModel() case TokenInstance: return p.parseShowInstance() case TokenBalance: return p.parseShowBalance() case TokenTask: return p.parseShowTask() case TokenQuotedString: return p.parseShowQuotedStringCommand() default: return nil, fmt.Errorf("unknown SHOW target: %s", p.curToken.Value) } } func (p *Parser) parseShowUser() (*Command, error) { p.nextToken() // consume USER // Check for PERMISSION if p.curToken.Type == TokenPermission { p.nextToken() userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("show_user_permission") cmd.Params["user_name"] = userName p.nextToken() // Semicolon is optional for SHOW TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("show_user") cmd.Params["user_name"] = userName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseShowRole() (*Command, error) { p.nextToken() // consume ROLE roleName, err := p.parseIdentifier() if err != nil { return nil, err } cmd := NewCommand("show_role") cmd.Params["role_name"] = roleName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseShowVariable() (*Command, error) { p.nextToken() // consume VAR varName, err := p.parseIdentifier() if err != nil { return nil, err } cmd := NewCommand("show_variable") cmd.Params["var_name"] = varName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseShowService() (*Command, error) { p.nextToken() // consume SERVICE serviceNum, err := p.parseNumber() if err != nil { return nil, err } cmd := NewCommand("show_service") cmd.Params["number"] = serviceNum p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseShowModel() (*Command, error) { p.nextToken() // consume model modelName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected model name: %w", err) } cmd := NewCommand("show_model") cmd.Params["model_name"] = modelName p.nextToken() // consume model_name if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() // consume from providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name: %w", err) } cmd.Params["provider_name"] = providerName p.nextToken() // consume provider name // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseShowProvider parses SHOW PROVIDER command func (p *Parser) parseShowProvider() (*Command, error) { p.nextToken() // consume PROVIDER providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name: %w", err) } cmd := NewCommand("show_provider") cmd.Params["provider_name"] = providerName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseCreateCommand() (*Command, error) { p.nextToken() // consume CREATE switch p.curToken.Type { case TokenUser: return p.parseCreateUser() case TokenRole: return p.parseCreateRole() case TokenModel: return p.parseCreateModelProvider() case TokenDataset: return p.parseCreateDataset() case TokenChat: return p.parseCreateChat() case TokenToken: return p.parseCreateToken() case TokenDatasetTable: return p.parseCreateDatasetTable() case TokenMetadata: return p.parseCreateMetadataTable() case TokenProvider: return p.parseCreateProviderInstance() default: return nil, fmt.Errorf("unknown CREATE target: %s", p.curToken.Value) } } func (p *Parser) parseAddCommand() (*Command, error) { p.nextToken() // consume ADD switch p.curToken.Type { case TokenProvider: return p.parseAddProvider() case TokenModel: return p.parseAddModel() default: return nil, fmt.Errorf("unknown ADD target: %s", p.curToken.Value) } } func (p *Parser) parseCreateToken() (*Command, error) { p.nextToken() // consume TOKEN // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("create_token"), nil } // Internal CLI for GO // parseCreateDatasetTable parses: CREATE DATASET TABLE 'name' VECTOR SIZE N func (p *Parser) parseCreateDatasetTable() (*Command, error) { p.nextToken() // consume DATASET TABLE compound token datasetName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected dataset name, got %s", p.curToken.Value) } p.nextToken() if p.curToken.Type != TokenVector { return nil, fmt.Errorf("expected VECTOR after dataset name, got %s", p.curToken.Value) } p.nextToken() if p.curToken.Type != TokenSize { return nil, fmt.Errorf("expected SIZE after VECTOR, got %s", p.curToken.Value) } p.nextToken() if p.curToken.Type != TokenInteger { return nil, fmt.Errorf("expected vector size number, got %s", p.curToken.Value) } vectorSize, err := strconv.Atoi(p.curToken.Value) if err != nil { return nil, fmt.Errorf("invalid vector size: %s", p.curToken.Value) } p.nextToken() if p.curToken.Type == TokenSemicolon { p.nextToken() } cmd := NewCommand("create_dataset_table") cmd.Params["dataset_name"] = datasetName cmd.Params["vector_size"] = vectorSize return cmd, nil } // Internal CLI for GO // parseCreateMetadataTable parses: CREATE METADATA TABLE func (p *Parser) parseCreateMetadataTable() (*Command, error) { // CREATE METADATA TABLE p.nextToken() // consume METADATA if p.curToken.Type != TokenTable { return nil, fmt.Errorf("expected TABLE after METADATA, got %s", p.curToken.Value) } p.nextToken() if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("create_metadata_table"), nil } func (p *Parser) parseCreateUser() (*Command, error) { p.nextToken() // consume USER userName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() password, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("create_user") cmd.Params["user_name"] = userName cmd.Params["password"] = password cmd.Params["role"] = "user" p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseCreateRole() (*Command, error) { p.nextToken() // consume ROLE roleName, err := p.parseIdentifier() if err != nil { return nil, err } cmd := NewCommand("create_role") cmd.Params["role_name"] = roleName p.nextToken() if p.curToken.Type == TokenDescription { p.nextToken() description, err := p.parseQuotedString() if err != nil { return nil, err } cmd.Params["description"] = description p.nextToken() } // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseCreateModelProvider() (*Command, error) { p.nextToken() // consume MODEL if p.curToken.Type != TokenProvider { return nil, fmt.Errorf("expected PROVIDER") } p.nextToken() providerName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() providerKey, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("create_model_provider") cmd.Params["provider_name"] = providerName cmd.Params["provider_key"] = providerKey p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseAddProvider parses ADD PROVIDER commands // ADD PROVIDER // ADD PROVIDER func (p *Parser) parseAddProvider() (*Command, error) { p.nextToken() // consume PROVIDER providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name: %w", err) } cmd := NewCommand("add_provider") cmd.Params["provider_name"] = providerName p.nextToken() // Check if api_key is provided (optional) if p.curToken.Type == TokenQuotedString { apiKey, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected api key: %w", err) } cmd.Params["api_key"] = apiKey p.nextToken() } // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // syntax: add model 'xxx' to provider 'vllm' instance 'test' with tokens 1024 chat think vision; func (p *Parser) parseAddModel() (*Command, error) { p.nextToken() // consume MODEL if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected model name") } modelName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() // consume model name if p.curToken.Type != TokenTo { return nil, fmt.Errorf("expected TO") } p.nextToken() if p.curToken.Type != TokenProvider { return nil, fmt.Errorf("expected PROVIDER") } p.nextToken() // provider name if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected provider name") } providerName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenInstance { return nil, fmt.Errorf("expected INSTANCE") } p.nextToken() // instance name if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected provider name") } instanceName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() var modelTypes []string var supportThink *bool = nil maxTokens := 0 if p.curToken.Type == TokenWith { p.nextToken() // pass WITH optionsLoop: for { switch p.curToken.Type { case TokenThink: if supportThink != nil { return nil, fmt.Errorf("think model is already set") } supportThink = new(bool) p.nextToken() *supportThink = true case TokenVision: p.nextToken() modelTypes = append(modelTypes, "vision") case TokenChat: p.nextToken() modelTypes = append(modelTypes, "chat") case TokenEmbedding: p.nextToken() modelTypes = append(modelTypes, "embedding") case TokenRerank: p.nextToken() modelTypes = append(modelTypes, "rerank") case TokenOCR: p.nextToken() modelTypes = append(modelTypes, "ocr") case TokenTTS: p.nextToken() modelTypes = append(modelTypes, "tts") case TokenASR: p.nextToken() modelTypes = append(modelTypes, "asr") case TokenTokens: p.nextToken() // pass TOKENS if maxTokens != 0 { return nil, fmt.Errorf("max tokens is already given %d", maxTokens) } if p.curToken.Type != TokenInteger { return nil, fmt.Errorf("expected integer") } maxTokens, err = p.parseNumber() if err != nil { return nil, err } p.nextToken() // consume case TokenSemicolon: p.nextToken() break optionsLoop // done default: // No more options to process break optionsLoop } } } cmd := NewCommand("add_custom_model") cmd.Params["model_name"] = modelName cmd.Params["model_types"] = modelTypes cmd.Params["provider_name"] = providerName cmd.Params["instance_name"] = instanceName if supportThink != nil { cmd.Params["support_think"] = *supportThink } cmd.Params["max_tokens"] = maxTokens return cmd, nil } func (p *Parser) parseCreateDataset() (*Command, error) { p.nextToken() // consume DATASET datasetName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenWith { return nil, fmt.Errorf("expected WITH") } p.nextToken() if p.curToken.Type != TokenEmbedding { return nil, fmt.Errorf("expected EMBEDDING") } p.nextToken() embedding, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() cmd := NewCommand("create_user_dataset") cmd.Params["dataset_name"] = datasetName cmd.Params["embedding"] = embedding if p.curToken.Type == TokenParser { p.nextToken() parserType, err := p.parseQuotedString() if err != nil { return nil, err } cmd.Params["parser_type"] = parserType p.nextToken() } else if p.curToken.Type == TokenPipeline { p.nextToken() pipeline, err := p.parseQuotedString() if err != nil { return nil, err } cmd.Params["pipeline"] = pipeline p.nextToken() } else { return nil, fmt.Errorf("expected PARSER or PIPELINE") } // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseCreateChat() (*Command, error) { p.nextToken() // consume CHAT chatName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("create_user_chat") cmd.Params["chat_name"] = chatName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseDropCommand() (*Command, error) { p.nextToken() // consume DROP switch p.curToken.Type { case TokenUser: return p.parseDropUser() case TokenRole: return p.parseDropRole() case TokenDataset: return p.parseDropDataset() case TokenChat: return p.parseDropChat() case TokenToken: return p.parseDropToken() case TokenDatasetTable: return p.parseDropDatasetTable() case TokenMetadata: return p.parseDropMetadataTable() case TokenInstance: return p.parseDropInstance() case TokenModel: return p.parseDropInstanceModel() default: return nil, fmt.Errorf("unknown DROP target: %s", p.curToken.Value) } } func (p *Parser) parseDeleteCommand() (*Command, error) { p.nextToken() // consume DELETE switch p.curToken.Type { case TokenProvider: return p.parseDeleteProvider() default: return nil, fmt.Errorf("unknown DROP target: %s", p.curToken.Value) } } func (p *Parser) parseRemoveCommand() (*Command, error) { p.nextToken() // consume RM switch p.curToken.Type { case TokenTag: return p.parseRemoveTags() case TokenChunks, TokenAll: return p.parseRemoveChunk() default: return nil, fmt.Errorf("unknown REMOVE target: %s", p.curToken.Value) } } func (p *Parser) parseDropToken() (*Command, error) { p.nextToken() // consume TOKEN tokenValue, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenOf { return nil, fmt.Errorf("expected OF") } p.nextToken() userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("drop_token") cmd.Params["token"] = tokenValue cmd.Params["user_name"] = userName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // Internal CLI for GO // parseDropDatasetTable parses: DROP DATASET TABLE 'name' func (p *Parser) parseDropDatasetTable() (*Command, error) { p.nextToken() // consume DATASET TABLE datasetName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected dataset name, got %s", p.curToken.Value) } p.nextToken() if p.curToken.Type == TokenSemicolon { p.nextToken() } cmd := NewCommand("drop_dataset_table") cmd.Params["dataset_name"] = datasetName return cmd, nil } // Internal CLI for GO // parseDropMetadataTable parses: DROP METADATA TABLE func (p *Parser) parseDropMetadataTable() (*Command, error) { // DROP METADATA TABLE p.nextToken() // consume METADATA if p.curToken.Type != TokenTable { return nil, fmt.Errorf("expected TABLE after METADATA, got %s", p.curToken.Value) } p.nextToken() if p.curToken.Type == TokenSemicolon { p.nextToken() } cmd := NewCommand("drop_metadata_table") return cmd, nil } func (p *Parser) parseDropUser() (*Command, error) { p.nextToken() // consume USER userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("drop_user") cmd.Params["user_name"] = userName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseDropRole() (*Command, error) { p.nextToken() // consume ROLE roleName, err := p.parseIdentifier() if err != nil { return nil, err } cmd := NewCommand("drop_role") cmd.Params["role_name"] = roleName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseDeleteProvider parses DELETE PROVIDER command func (p *Parser) parseDeleteProvider() (*Command, error) { p.nextToken() // consume PROVIDER providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name: %w", err) } cmd := NewCommand("delete_provider") cmd.Params["provider_name"] = providerName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseDropDataset() (*Command, error) { p.nextToken() // consume DATASET datasetName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("drop_user_dataset") cmd.Params["dataset_name"] = datasetName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseDropChat() (*Command, error) { p.nextToken() // consume CHAT chatName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("drop_user_chat") cmd.Params["chat_name"] = chatName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseAlterCommand() (*Command, error) { p.nextToken() // consume ALTER switch p.curToken.Type { case TokenUser: return p.parseAlterUser() case TokenRole: return p.parseAlterRole() case TokenProvider: return p.parseAlterProvider() case TokenInstance: return p.parseAlterInstance() default: return nil, fmt.Errorf("unknown ALTER target: %s", p.curToken.Value) } } func (p *Parser) parseAlterUser() (*Command, error) { p.nextToken() // consume USER if p.curToken.Type == TokenActive { return p.parseActivateUser() } if p.curToken.Type == TokenPassword { p.nextToken() userName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() password, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("alter_user") cmd.Params["user_name"] = userName cmd.Params["password"] = password p.nextToken() // Semicolon is optional for SHOW TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } userName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenSet { return nil, fmt.Errorf("expected SET") } p.nextToken() if p.curToken.Type != TokenRole { return nil, fmt.Errorf("expected ROLE") } p.nextToken() roleName, err := p.parseIdentifier() if err != nil { return nil, err } cmd := NewCommand("alter_user_role") cmd.Params["user_name"] = userName cmd.Params["role_name"] = roleName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseActivateUser() (*Command, error) { p.nextToken() // consume ACTIVE userName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() // Accept 'on' or 'off' as identifier status := p.curToken.Value if status != "on" && status != "off" { return nil, fmt.Errorf("expected 'on' or 'off', got %s", p.curToken.Value) } cmd := NewCommand("activate_user") cmd.Params["user_name"] = userName cmd.Params["activate_status"] = status p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseAlterRole() (*Command, error) { p.nextToken() // consume ROLE roleName, err := p.parseIdentifier() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenSet { return nil, fmt.Errorf("expected SET") } p.nextToken() if p.curToken.Type != TokenDescription { return nil, fmt.Errorf("expected DESCRIPTION") } p.nextToken() description, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("alter_role") cmd.Params["role_name"] = roleName cmd.Params["description"] = description p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseAlterProvider parses ALTER PROVIDER NAME command func (p *Parser) parseAlterProvider() (*Command, error) { p.nextToken() // consume PROVIDER providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name: %w", err) } p.nextToken() if p.curToken.Type != TokenName { return nil, fmt.Errorf("expected NAME") } p.nextToken() newName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected new provider name: %w", err) } cmd := NewCommand("alter_provider") cmd.Params["provider_name"] = providerName cmd.Params["new_name"] = newName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseCreateProviderInstance parses CREATE PROVIDER INSTANCE KEY URL command // instance_name cannot be "default" func (p *Parser) parseCreateProviderInstance() (*Command, error) { p.nextToken() // consume PROVIDER providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name: %w", err) } p.nextToken() if p.curToken.Type != TokenInstance { return nil, fmt.Errorf("expected INSTANCE after provider name") } p.nextToken() instanceName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected instance name: %w", err) } p.nextToken() if p.curToken.Type != TokenKey { return nil, fmt.Errorf("expected KEY after instance name") } p.nextToken() apiKey, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected API key: %w", err) } p.nextToken() baseURL := "" if p.curToken.Type == TokenURL { p.nextToken() baseURL, err = p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected base URL: %w", err) } p.nextToken() } region := "" if p.curToken.Type == TokenRegion { p.nextToken() region, err = p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected base URL: %w", err) } p.nextToken() } cmd := NewCommand("create_provider_instance") cmd.Params["provider_name"] = providerName cmd.Params["instance_name"] = instanceName cmd.Params["api_key"] = apiKey if baseURL != "" { // Only local model provider need to set URL cmd.Params["base_url"] = baseURL if region == "" { region = instanceName } } if region != "" { cmd.Params["region"] = region } p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseListInstances parses LIST INSTANCES FROM PROVIDER command func (p *Parser) parseListInstances() (*Command, error) { p.nextToken() // consume INSTANCES if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err) } cmd := NewCommand("list_provider_instances") cmd.Params["provider_name"] = providerName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseShowInstance parses SHOW INSTANCE FROM PROVIDER command func (p *Parser) parseShowInstance() (*Command, error) { p.nextToken() // consume INSTANCE instanceName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected instance name: %w", err) } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err) } cmd := NewCommand("show_provider_instance") cmd.Params["instance_name"] = instanceName cmd.Params["provider_name"] = providerName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseShowInstance parses SHOW BALANCE FROM func (p *Parser) parseShowBalance() (*Command, error) { p.nextToken() // consume INSTANCE if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected provider name after FROM PROVIDER") } providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err) } p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected instance name") } instanceName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected instance name: %w", err) } p.nextToken() cmd := NewCommand("show_instance_balance") cmd.Params["instance_name"] = instanceName cmd.Params["provider_name"] = providerName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseShowTask parses SHOW TASK func (p *Parser) parseShowTask() (*Command, error) { p.nextToken() // consume TASK taskID, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected string: %w", err) } p.nextToken() cmd := NewCommand("show_task_user_command") cmd.Params["task_id"] = taskID p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseAlterInstance parses ALTER INSTANCE NAME FROM PROVIDER command func (p *Parser) parseAlterInstance() (*Command, error) { p.nextToken() // consume INSTANCE instanceName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected instance name: %w", err) } p.nextToken() if p.curToken.Type != TokenName { return nil, fmt.Errorf("expected NAME") } p.nextToken() newName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected new instance name: %w", err) } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() if p.curToken.Type != TokenProvider { return nil, fmt.Errorf("expected PROVIDER after FROM") } p.nextToken() providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err) } cmd := NewCommand("alter_provider_instance") cmd.Params["instance_name"] = instanceName cmd.Params["new_name"] = newName cmd.Params["provider_name"] = providerName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseDropInstance parses DROP INSTANCE FROM PROVIDER command func (p *Parser) parseDropInstance() (*Command, error) { p.nextToken() // consume INSTANCE instanceName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected instance name: %w", err) } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err) } cmd := NewCommand("drop_provider_instance") cmd.Params["instance_name"] = instanceName cmd.Params["provider_name"] = providerName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseDropInstanceModel parses DROP MODEL FROM command // Only works for local deployed model func (p *Parser) parseDropInstanceModel() (*Command, error) { p.nextToken() // consume MODEL modelName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected instance name: %w", err) } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() providerName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected provider name after FROM PROVIDER: %w", err) } p.nextToken() instanceName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected instance name after provider name: %w", err) } p.nextToken() cmd := NewCommand("drop_instance_model") cmd.Params["instance_name"] = instanceName cmd.Params["provider_name"] = providerName cmd.Params["model_name"] = modelName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseGrantCommand() (*Command, error) { p.nextToken() // consume GRANT if p.curToken.Type == TokenAdmin { return p.parseGrantAdmin() } return p.parseGrantPermission() } func (p *Parser) parseGrantAdmin() (*Command, error) { p.nextToken() // consume ADMIN userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("grant_admin") cmd.Params["user_name"] = userName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseGrantPermission() (*Command, error) { actions, err := p.parseIdentifierList() if err != nil { return nil, err } if p.curToken.Type != TokenOn { return nil, fmt.Errorf("expected ON") } p.nextToken() resource, err := p.parseIdentifier() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenTo { return nil, fmt.Errorf("expected TO") } p.nextToken() if p.curToken.Type != TokenRole { return nil, fmt.Errorf("expected ROLE") } p.nextToken() roleName, err := p.parseIdentifier() if err != nil { return nil, err } cmd := NewCommand("grant_permission") cmd.Params["actions"] = actions cmd.Params["resource"] = resource cmd.Params["role_name"] = roleName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseRevokeCommand() (*Command, error) { p.nextToken() // consume REVOKE if p.curToken.Type == TokenAdmin { return p.parseRevokeAdmin() } return p.parseRevokePermission() } func (p *Parser) parseRevokeAdmin() (*Command, error) { p.nextToken() // consume ADMIN userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("revoke_admin") cmd.Params["user_name"] = userName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseRevokePermission() (*Command, error) { actions, err := p.parseIdentifierList() if err != nil { return nil, err } if p.curToken.Type != TokenOn { return nil, fmt.Errorf("expected ON") } p.nextToken() resource, err := p.parseIdentifier() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() if p.curToken.Type != TokenRole { return nil, fmt.Errorf("expected ROLE") } p.nextToken() roleName, err := p.parseIdentifier() if err != nil { return nil, err } cmd := NewCommand("revoke_permission") cmd.Params["actions"] = actions cmd.Params["resource"] = resource cmd.Params["role_name"] = roleName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseIdentifierList() ([]string, error) { var list []string ident, err := p.parseIdentifier() if err != nil { return nil, err } list = append(list, ident) p.nextToken() for p.curToken.Type == TokenComma { p.nextToken() ident, err := p.parseIdentifier() if err != nil { return nil, err } list = append(list, ident) p.nextToken() } return list, nil } func (p *Parser) parseSetCommand() (*Command, error) { p.nextToken() // consume SET if p.curToken.Type == TokenVar { return p.parseSetVariable() } if p.curToken.Type == TokenDefault { return p.parseSetDefault() } if p.curToken.Type == TokenToken { return p.parseSetToken() } if p.curToken.Type == TokenMetadata { return p.parseSetMeta() } if p.curToken.Type == TokenLog { return p.parseSetLog() } return nil, fmt.Errorf("unknown SET target: %s", p.curToken.Value) } func (p *Parser) parseSetVariable() (*Command, error) { p.nextToken() // consume VAR varName, err := p.parseIdentifier() if err != nil { return nil, err } p.nextToken() varValue, err := p.parseVariableValue() if err != nil { return nil, err } cmd := NewCommand("set_variable") cmd.Params["var_name"] = varName cmd.Params["var_value"] = varValue p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseSetDefault() (*Command, error) { p.nextToken() // consume DEFAULT var modelType, compositeModelName string var err error switch p.curToken.Type { case TokenChat: modelType = "chat" case TokenVision: modelType = "vision" case TokenEmbedding: modelType = "embedding" case TokenRerank: modelType = "rerank" case TokenASR: modelType = "asr" case TokenTTS: modelType = "tts" case TokenOCR: modelType = "ocr" default: return nil, fmt.Errorf("unknown model type: %s", p.curToken.Value) } p.nextToken() // pass model type if p.curToken.Type != TokenModel { return nil, fmt.Errorf("expected MODEL") } p.nextToken() // pass MODEL // Format: 'provider/instance/model' or just 'message' if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected quoted string with format provider/instance/model") } compositeModelName, err = p.parseQuotedString() if err != nil { return nil, err } p.nextToken() cmd := NewCommand("set_default_model") cmd.Params["model_type"] = modelType cmd.Params["composite_model_name"] = compositeModelName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseSetToken() (*Command, error) { p.nextToken() // consume TOKEN tokenValue, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("set_token") cmd.Params["token"] = tokenValue p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseSetLog() (*Command, error) { p.nextToken() // consume LOG switch p.curToken.Type { case TokenLevel: return p.parseSetLogLevel() default: return nil, fmt.Errorf("unknown log target: %s", p.curToken.Value) } } func (p *Parser) parseSetLogLevel() (*Command, error) { p.nextToken() // consume LEVEL cmd := NewCommand("set_log_level") switch p.curToken.Type { case TokenDebug: cmd.Params["level"] = "debug" case TokenInfo: cmd.Params["level"] = "info" case TokenWarn: cmd.Params["level"] = "warn" case TokenError: cmd.Params["level"] = "error" case TokenFatal: cmd.Params["level"] = "fatal" case TokenPanic: cmd.Params["level"] = "panic" default: return nil, fmt.Errorf("unknown log target: %s", p.curToken.Value) } p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseResetCommand() (*Command, error) { p.nextToken() // consume RESET if p.curToken.Type != TokenDefault { return nil, fmt.Errorf("expected DEFAULT") } p.nextToken() var modelType string switch p.curToken.Type { case TokenChat: modelType = "chat" case TokenVision: modelType = "vision" case TokenEmbedding: modelType = "embedding" case TokenRerank: modelType = "rerank" case TokenASR: modelType = "asr" case TokenTTS: modelType = "tts" case TokenOCR: modelType = "ocr" default: return nil, fmt.Errorf("unknown model type: %s", p.curToken.Value) } cmd := NewCommand("reset_default_model") cmd.Params["model_type"] = modelType p.nextToken() if p.curToken.Type != TokenModel { return nil, fmt.Errorf("expected MODEL") } p.nextToken() // pass MODEL // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseGenerateCommand() (*Command, error) { p.nextToken() // consume GENERATE if p.curToken.Type != TokenToken { return nil, fmt.Errorf("expected TOKEN") } p.nextToken() if p.curToken.Type != TokenFor { return nil, fmt.Errorf("expected FOR") } p.nextToken() if p.curToken.Type != TokenUser { return nil, fmt.Errorf("expected USER") } p.nextToken() userName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("generate_token") cmd.Params["user_name"] = userName p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseImportCommand() (*Command, error) { p.nextToken() // consume IMPORT documentPaths, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenInto { return nil, fmt.Errorf("expected INTO") } p.nextToken() if p.curToken.Type != TokenDataset { return nil, fmt.Errorf("expected DATASET") } p.nextToken() datasetName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("import_docs_into_dataset") cmd.Params["document_paths"] = documentPaths cmd.Params["dataset_name"] = datasetName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseInsertCommand parses INSERT command and dispatches to specific handler func (p *Parser) parseInsertCommand() (*Command, error) { p.nextToken() // consume INSERT // Expect DATASET or METADATA if p.curToken.Type == TokenDataset { return p.parseInsertDatasetFromFile() } if p.curToken.Type == TokenMetadata { return p.parseInsertMetadataFromFile() } return nil, fmt.Errorf("expected DATASET or METADATA after INSERT, got %s", p.curToken.Value) } // Internal CLI for GO // parseInsertDatasetFromFile parses: INSERT DATASET FROM FILE "file_path" func (p *Parser) parseInsertDatasetFromFile() (*Command, error) { p.nextToken() // consume DATASET // Expect FROM if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM, got %s", p.curToken.Value) } p.nextToken() // Expect FILE if p.curToken.Type != TokenFile { return nil, fmt.Errorf("expected FILE, got %s", p.curToken.Value) } p.nextToken() // Get file path (quoted string) filePath, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("insert_dataset_from_file") cmd.Params["file_path"] = filePath p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // Internal CLI for GO // parseInsertMetadataFromFile parses: INSERT METADATA FROM FILE "file_path" func (p *Parser) parseInsertMetadataFromFile() (*Command, error) { p.nextToken() // consume METADATA // Expect FROM if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM, got %s", p.curToken.Value) } p.nextToken() // Expect FILE if p.curToken.Type != TokenFile { return nil, fmt.Errorf("expected FILE, got %s", p.curToken.Value) } p.nextToken() // Get file path (quoted string) filePath, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("insert_metadata_from_file") cmd.Params["file_path"] = filePath p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseSearchCommand() (*Command, error) { p.nextToken() // consume SEARCH var err error var question string if p.curToken.Type == TokenQuotedString { question, err = p.parseQuotedString() if err != nil { return nil, err } } else if p.curToken.Type == TokenIdentifier { question, err = p.parseIdentifier() if err != nil { return nil, err } } else { return nil, fmt.Errorf("expected quoted string or identifier") } p.nextToken() if p.curToken.Type == TokenOn { p.nextToken() // skip on if p.curToken.Type != TokenDatasets { return nil, fmt.Errorf("expected DATASETS") } p.nextToken() datasets, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("search_on_datasets") cmd.Params["question"] = question cmd.Params["datasets"] = datasets p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } cmd := NewCommand("ce_search") cmd.Params["query"] = question if p.curToken.Type == TokenEOF { cmd.Params["path"] = "." return cmd, nil } for p.curToken.Type != TokenEOF { if p.curToken.Type == TokenDash { p.nextToken() // skip dash if p.curToken.Type != TokenIdentifier { return nil, fmt.Errorf("expect identifier") } if strings.ToLower(p.curToken.Value) == "n" { p.nextToken() var err error if p.curToken.Type != TokenInteger { return nil, fmt.Errorf("expect number") } cmd.Params["number"], err = p.parseNumber() if err != nil { return nil, err } p.nextToken() continue } //if strings.ToLower(p.curToken.Value) == "t" { // p.nextToken() // var err error // if p.curToken.Type != TokenInteger { // return nil, fmt.Errorf("expect number") // } // cmd.Params["threshold"], err = p.parseFloat() // if err != nil { // return nil, err // } // p.nextToken() // continue //} return nil, fmt.Errorf("unknow parameter: %s", p.curToken.Value) } else if p.curToken.Type == TokenIdentifier { if cmd.Params["path"] == nil { cmd.Params["path"] = p.curToken.Value } else { cmd.Params["path"] = fmt.Sprintf("%s%s", cmd.Params["path"], p.curToken.Value) } p.nextToken() // skip path continue } else if p.curToken.Type == TokenSlash { if cmd.Params["path"] == nil { cmd.Params["path"] = "/" } else { cmd.Params["path"] = fmt.Sprintf("%s/", cmd.Params["path"]) } p.nextToken() // skip slash if p.curToken.Type == TokenIdentifier { cmd.Params["path"] = fmt.Sprintf("%s%s", cmd.Params["path"], p.curToken.Value) p.nextToken() } continue } } return cmd, nil } func (p *Parser) parseListModelsOfProvider() (*Command, error) { if p.curToken.Type == TokenSupported { // List supported models p.nextToken() cmd := NewCommand("list_supported_models") if p.curToken.Type != TokenModels { return nil, fmt.Errorf("expected MODELS") } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected quoted string for provider name") } firstName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected quoted string for instance name") } secondName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() cmd.Params["provider_name"] = firstName cmd.Params["instance_name"] = secondName // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } if p.curToken.Type != TokenModels { return nil, fmt.Errorf("expected MODELS") } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() // Parse first quoted string (could be instance_name or provider_name) firstName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() // Check if there's a second quoted string (provider_name) // If so, format is: LIST MODELS FROM // If not, format is: LIST MODELS FROM if p.curToken.Type == TokenQuotedString { // Two arguments: instance_name and provider_name instanceName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("list_instance_models") cmd.Params["instance_name"] = instanceName cmd.Params["provider_name"] = firstName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // Only one argument: provider_name cmd := NewCommand("list_provider_models") cmd.Params["provider_name"] = firstName // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseEnableCommand() (*Command, error) { p.nextToken() // consume ENABLE if p.curToken.Type != TokenModel { return nil, fmt.Errorf("expected MODEL") } p.nextToken() modelName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() modelProvider, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() modelInstance, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } cmd := NewCommand("enable_model") cmd.Params["model_name"] = modelName cmd.Params["instance_name"] = modelInstance cmd.Params["provider_name"] = modelProvider return cmd, nil } func (p *Parser) parseDisableCommand() (*Command, error) { p.nextToken() // consume DISABLE if p.curToken.Type != TokenModel { return nil, fmt.Errorf("expected MODEL") } p.nextToken() modelName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM") } p.nextToken() modelProvider, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() modelInstance, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } cmd := NewCommand("disable_model") cmd.Params["model_name"] = modelName cmd.Params["instance_name"] = modelInstance cmd.Params["provider_name"] = modelProvider return cmd, nil } // CHAT 'model@instance@provider' 'hello world' // CHAT WITH 'model@instance@provider' MESSAGE 'hello world' 'who are you' IMAGE 'url1' 'file0' VIDEO "url2.mov" "file1" FILE "url" "path file2" AUDIO "file.wav" func (p *Parser) parseChatCommand() (*Command, error) { p.nextToken() // consume CHAT var err error var compositeModelName string = "" var messages []string var images []string var videos []string var audios []string var files []string effort := "default" verbosity := "low" optionsLoop: for { switch p.curToken.Type { case TokenWith: p.nextToken() // 'model@instance@provider' if compositeModelName != "" { return nil, fmt.Errorf("model name is already set") } compositeModelName, err = p.parseQuotedString() if err != nil { return nil, err } p.nextToken() case TokenMessage: p.nextToken() if len(messages) != 0 { return nil, fmt.Errorf("message is already set") } messageLoop: for { if p.curToken.Type != TokenQuotedString { break messageLoop } var message string message, err = p.parseQuotedString() if err != nil { return nil, err } message = strings.TrimSpace(message) messages = append(messages, message) p.nextToken() } case TokenImage: p.nextToken() if len(images) != 0 { return nil, fmt.Errorf("image is already set") } imageLoop: for { if p.curToken.Type != TokenQuotedString { break imageLoop } var image string image, err = p.parseQuotedString() if err != nil { return nil, err } images = append(images, image) p.nextToken() } case TokenVideo: p.nextToken() if len(videos) != 0 { return nil, fmt.Errorf("video is already set") } videoLoop: for { if p.curToken.Type != TokenQuotedString { break videoLoop } var video string video, err = p.parseQuotedString() if err != nil { return nil, err } videos = append(videos, video) p.nextToken() } case TokenAudio: p.nextToken() if len(audios) != 0 { return nil, fmt.Errorf("video is already set") } audioLoop: for { if p.curToken.Type != TokenQuotedString { break audioLoop } var audio string audio, err = p.parseQuotedString() if err != nil { return nil, err } audios = append(audios, audio) p.nextToken() } case TokenFile: p.nextToken() if len(files) != 0 { return nil, fmt.Errorf("video is already set") } fileLoop: for { if p.curToken.Type != TokenQuotedString { break fileLoop } var file string file, err = p.parseQuotedString() if err != nil { return nil, err } files = append(files, file) p.nextToken() } case TokenEffort: p.nextToken() // pass Effort switch p.curToken.Type { case TokenNone: effort = "none" case TokenMinimal: effort = "minimal" case TokenLow: effort = "low" case TokenMedium: effort = "medium" case TokenHigh: effort = "high" case TokenMax: effort = "max" default: return nil, fmt.Errorf("invalid effort level") } p.nextToken() break optionsLoop case TokenVerbosity: p.nextToken() // pass VERBOSITY switch p.curToken.Type { case TokenLow: verbosity = "low" case TokenMedium: verbosity = "median" case TokenHigh: verbosity = "high" default: return nil, fmt.Errorf("invalid verbosity level") } p.nextToken() break optionsLoop case TokenSemicolon: p.nextToken() break optionsLoop // done default: // No more options to process break optionsLoop } } cmd := NewCommand("chat_to_model") cmd.Params["composite_model_name"] = compositeModelName cmd.Params["messages"] = messages cmd.Params["images"] = images cmd.Params["videos"] = videos cmd.Params["audios"] = audios cmd.Params["files"] = files cmd.Params["thinking"] = false cmd.Params["stream"] = false cmd.Params["effort"] = effort cmd.Params["verbosity"] = verbosity return cmd, nil } func (p *Parser) parseThinkCommand() (*Command, error) { p.nextToken() // consume THINK if p.curToken.Type != TokenChat { return nil, fmt.Errorf("expected CHAT after THINK") } command, err := p.parseChatCommand() if err != nil { return nil, err } command.Params["thinking"] = true return command, nil } func (p *Parser) parseStreamCommand() (*Command, error) { p.nextToken() // consume STREAM var command *Command var err error switch p.curToken.Type { case TokenChat: command, err = p.parseChatCommand() if err != nil { return nil, err } case TokenThink: command, err = p.parseThinkCommand() if err != nil { return nil, err } case TokenASR: command, err = p.parseASRCommand() if err != nil { return nil, err } case TokenTTS: command, err = p.parseTTSCommand() if err != nil { return nil, err } default: return nil, fmt.Errorf("expected CHAT, THINK, ASR, or TTS after STREAM") } command.Params["stream"] = true return command, nil } func (p *Parser) parseEmbedCommand() (*Command, error) { p.nextToken() // consume EMBED if p.curToken.Type != TokenText { return nil, fmt.Errorf("expected WITH after EMBED") } p.nextToken() // consume TEXT var texts []string textLoop: for { if p.curToken.Type != TokenQuotedString { break textLoop } text, err := p.parseQuotedString() if err != nil { return nil, err } text = strings.TrimSpace(text) texts = append(texts, text) p.nextToken() } if p.curToken.Type != TokenWith { return nil, fmt.Errorf("expected WITH after EMBED") } p.nextToken() // consume WITH compositeModelName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenDimension { return nil, fmt.Errorf("expected DIMENSION") } p.nextToken() // consume WITH dimension, err := p.parseNumber() if err != nil { return nil, err } p.nextToken() cmd := NewCommand("embed_user_text") cmd.Params["composite_model_name"] = compositeModelName cmd.Params["texts"] = texts cmd.Params["dimension"] = dimension return cmd, nil } func (p *Parser) parseRerankCommand() (*Command, error) { p.nextToken() // consume RERANK if p.curToken.Type != TokenQuery { return nil, fmt.Errorf("expected WITH after EMBED") } p.nextToken() // consume QUERY query, err := p.parseQuotedString() if err != nil { return nil, err } query = strings.TrimSpace(query) p.nextToken() // consume query if p.curToken.Type != TokenDocument { return nil, fmt.Errorf("expected DOCUMENT after query") } p.nextToken() // consume DOCUMENT var documents []string documentLoop: for { if p.curToken.Type != TokenQuotedString { break documentLoop } var document string document, err = p.parseQuotedString() if err != nil { return nil, err } document = strings.TrimSpace(document) documents = append(documents, document) p.nextToken() } if p.curToken.Type != TokenWith { return nil, fmt.Errorf("expected WITH after EMBED") } p.nextToken() // consume WITH compositeModelName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenTop { return nil, fmt.Errorf("expected TOP after model") } p.nextToken() topN, err := p.parseNumber() if err != nil { return nil, err } p.nextToken() cmd := NewCommand("rarank_user_document") cmd.Params["composite_model_name"] = compositeModelName cmd.Params["query"] = query cmd.Params["documents"] = documents cmd.Params["top_n"] = topN return cmd, nil } func (p *Parser) parseASRCommand() (*Command, error) { p.nextToken() // consume ASR if p.curToken.Type != TokenWith { return nil, fmt.Errorf("expected WITH after ASR") } p.nextToken() // consume WITH compositeModelName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenAudio { return nil, fmt.Errorf("expected AUDIO to ASR") } p.nextToken() // consume AUDIO audioFile, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() cmd := NewCommand("asr_user_command") cmd.Params["composite_model_name"] = compositeModelName cmd.Params["audio_file"] = audioFile for p.curToken.Type != TokenEOF && p.curToken.Type != TokenSemicolon { switch p.curToken.Type { case TokenParam: p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expect quoted string after 'param'") } cmd.Params["param_str"] = strings.Trim(p.curToken.Value, "\"'") p.nextToken() default: return nil, fmt.Errorf("unexpected token in asr command: %s", p.curToken.Value) } } // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseTTSCommand() (*Command, error) { p.nextToken() cmd := NewCommand("tts_user_command") if p.curToken.Type != TokenWith { return nil, fmt.Errorf("expect 'with' after tts") } p.nextToken() if p.curToken.Type != TokenQuotedString && p.curToken.Type != TokenIdentifier { return nil, fmt.Errorf("expect model name after 'with'") } cmd.Params["composite_model_name"] = strings.Trim(p.curToken.Value, "\"'") p.nextToken() if p.curToken.Type != TokenText { return nil, fmt.Errorf("expect 'text' parameter") } p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expect quoted string after 'text'") } cmd.Params["text"] = strings.Trim(p.curToken.Value, "\"'") p.nextToken() for p.curToken.Type != TokenEOF && p.curToken.Type != TokenSemicolon { switch p.curToken.Type { case TokenPlay: p.nextToken() cmd.Params["play"] = true case TokenParam: p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expect quoted string after 'param'") } cmd.Params["param_str"] = strings.Trim(p.curToken.Value, "\"'") p.nextToken() p.nextToken() case TokenSave: p.nextToken() if p.curToken.Type != TokenQuotedString && p.curToken.Type != TokenIdentifier { return nil, fmt.Errorf("expect directory path after 'save'") } cmd.Params["save"] = true cmd.Params["save_path"] = strings.Trim(p.curToken.Value, "\"'") p.nextToken() case TokenFormat: p.nextToken() if p.curToken.Type != TokenQuotedString && p.curToken.Type != TokenIdentifier { return nil, fmt.Errorf("expect format string (e.g. 'wav') after 'format'") } cmd.Params["format"] = strings.Trim(p.curToken.Value, "\"'") p.nextToken() default: return nil, fmt.Errorf("unexpected token: %s", p.curToken.Value) } } if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseOCRCommand() (*Command, error) { p.nextToken() // consume OCR if p.curToken.Type != TokenWith { return nil, fmt.Errorf("expected WITH after OCR") } p.nextToken() // consume WITH compositeModelName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() cmd := NewCommand("ocr_user_command") switch p.curToken.Type { case TokenFile: p.nextToken() var file string file, err = p.parseQuotedString() if err != nil { return nil, err } cmd.Params["file"] = file p.nextToken() case TokenURL: p.nextToken() var url string url, err = p.parseQuotedString() if err != nil { return nil, err } cmd.Params["url"] = url p.nextToken() default: return nil, fmt.Errorf("expected FILE or URL") } cmd.Params["composite_model_name"] = compositeModelName return cmd, nil } func (p *Parser) parseModelParseCommand() (*Command, error) { p.nextToken() // consume WITH compositeModelName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() cmd := NewCommand("parse_file_user_command") switch p.curToken.Type { case TokenFile: p.nextToken() var file string file, err = p.parseQuotedString() if err != nil { return nil, err } cmd.Params["file"] = file p.nextToken() case TokenURL: p.nextToken() var url string url, err = p.parseQuotedString() if err != nil { return nil, err } cmd.Params["url"] = url p.nextToken() default: return nil, fmt.Errorf("expected FILE or URL") } cmd.Params["composite_model_name"] = compositeModelName return cmd, nil } func (p *Parser) parseCheckCommand() (*Command, error) { p.nextToken() // consume CHECK if p.curToken.Type != TokenInstance { return nil, fmt.Errorf("expected INSTANCE after CHECK") } p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected instance name after INSTANCE") } instanceName := p.curToken.Value p.nextToken() if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM after instance name") } p.nextToken() if p.curToken.Type != TokenQuotedString { return nil, fmt.Errorf("expected provider name after FROM") } providerName := p.curToken.Value p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } cmd := NewCommand("check_provider_connection") cmd.Params["provider_name"] = providerName cmd.Params["instance_name"] = instanceName return cmd, nil } func (p *Parser) parseUseCommand() (*Command, error) { p.nextToken() // consume USE if p.curToken.Type != TokenModel { return nil, fmt.Errorf("expected MODEL after USE") } p.nextToken() // consume MODEL // Parse model identifier in format 'model@instance@provider' compositeModelName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected model identifier in format 'model@instance@provider': %w", err) } p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } cmd := NewCommand("use_model") cmd.Params["composite_model_name"] = compositeModelName return cmd, nil } func (p *Parser) parseParseCommand() (*Command, error) { p.nextToken() // consume PARSE switch p.curToken.Type { case TokenDataset: return p.parseParseDataset() case TokenWith: return p.parseModelParseCommand() default: return p.parseParseDocs() } } func (p *Parser) parseParseDataset() (*Command, error) { p.nextToken() // consume DATASET datasetName, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() var method string if p.curToken.Type == TokenSync { method = "sync" } else if p.curToken.Type == TokenAsync { method = "async" } else { return nil, fmt.Errorf("expected SYNC or ASYNC") } cmd := NewCommand("parse_dataset") cmd.Params["dataset_name"] = datasetName cmd.Params["method"] = method p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseParseDocs() (*Command, error) { documentNames, err := p.parseQuotedString() if err != nil { return nil, err } p.nextToken() if p.curToken.Type != TokenOf { return nil, fmt.Errorf("expected OF") } p.nextToken() if p.curToken.Type != TokenDataset { return nil, fmt.Errorf("expected DATASET") } p.nextToken() datasetName, err := p.parseQuotedString() if err != nil { return nil, err } cmd := NewCommand("parse_dataset_docs") cmd.Params["document_names"] = documentNames cmd.Params["dataset_name"] = datasetName p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseBenchmarkCommand() (*Command, error) { cmd := NewCommand("benchmark") p.nextToken() // consume BENCHMARK concurrency, err := p.parseNumber() if err != nil { return nil, err } cmd.Params["concurrency"] = concurrency p.nextToken() iterations, err := p.parseNumber() if err != nil { return nil, err } cmd.Params["iterations"] = iterations p.nextToken() // Parse user_statement nestedCmd, err := p.parseUserStatement() // Not only user statement if err != nil { return nil, err } cmd.Params["command"] = nestedCmd return cmd, nil } func (p *Parser) parseUserStatement() (*Command, error) { switch p.curToken.Type { case TokenPing: return p.parsePingServer() case TokenShow: return p.parseShowCommand() case TokenCreate: return p.parseCreateCommand() case TokenDrop: return p.parseDropCommand() case TokenSet: return p.parseSetCommand() case TokenUnset: return p.parseUnsetCommand() case TokenReset: return p.parseResetCommand() case TokenList: return p.parseListCommand() case TokenParse: return p.parseParseCommand() case TokenImport: return p.parseImportCommand() case TokenInsert: return p.parseInsertCommand() case TokenSearch: return p.parseSearchCommand() case TokenUpdate: return p.parseUpdateCommand() case TokenRemove: return p.parseRemoveCommand() default: return nil, fmt.Errorf("invalid user statement: %s", p.curToken.Value) } } func (p *Parser) parseStartupCommand() (*Command, error) { p.nextToken() // consume STARTUP if p.curToken.Type != TokenService { return nil, fmt.Errorf("expected SERVICE") } p.nextToken() serviceNum, err := p.parseNumber() if err != nil { return nil, err } cmd := NewCommand("startup_service") cmd.Params["number"] = serviceNum p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseShutdownCommand() (*Command, error) { p.nextToken() // consume SHUTDOWN if p.curToken.Type != TokenService { return nil, fmt.Errorf("expected SERVICE") } p.nextToken() serviceNum, err := p.parseNumber() if err != nil { return nil, err } cmd := NewCommand("shutdown_service") cmd.Params["number"] = serviceNum p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseRestartCommand() (*Command, error) { p.nextToken() // consume RESTART if p.curToken.Type != TokenService { return nil, fmt.Errorf("expected SERVICE") } p.nextToken() serviceNum, err := p.parseNumber() if err != nil { return nil, err } cmd := NewCommand("restart_service") cmd.Params["number"] = serviceNum p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } func (p *Parser) parseUnsetCommand() (*Command, error) { p.nextToken() // consume UNSET if p.curToken.Type != TokenToken { return nil, fmt.Errorf("expected TOKEN after UNSET") } p.nextToken() // Semicolon is optional for UNSET TOKEN if p.curToken.Type == TokenSemicolon { p.nextToken() } return NewCommand("unset_token"), nil } // Internal // parseUpdateCommand parses: UPDATE CHUNK 'chunk_id' OF DATASET 'dataset_name' SET '{"content": "..."}' func (p *Parser) parseUpdateCommand() (*Command, error) { p.nextToken() // consume UPDATE if p.curToken.Type == TokenChunk { return p.parseUpdateChunk() } return nil, fmt.Errorf("unknown UPDATE target: %s", p.curToken.Value) } // Internal CLI for GO // parseUpdateChunk parses: UPDATE CHUNK 'chunk_id' OF DATASET 'dataset_name' SET '{"content": "..."}' func (p *Parser) parseUpdateChunk() (*Command, error) { p.nextToken() // consume CHUNK // Parse chunk_id chunkID, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected chunk_id: %w", err) } cmd := NewCommand("update_chunk") cmd.Params["chunk_id"] = chunkID p.nextToken() if p.curToken.Type != TokenOf { return nil, fmt.Errorf("expected OF after chunk_id") } p.nextToken() if p.curToken.Type != TokenDataset { return nil, fmt.Errorf("expected DATASET after OF") } p.nextToken() // Parse dataset_name datasetName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected dataset_name: %w", err) } cmd.Params["dataset_name"] = datasetName p.nextToken() if p.curToken.Type != TokenSet { return nil, fmt.Errorf("expected SET after dataset_name") } p.nextToken() // Parse JSON body jsonBody, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected JSON body: %w", err) } cmd.Params["json_body"] = jsonBody p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseSetMeta parses: SET METADATA OF DOCUMENT 'doc_id' TO '{"key": "value"}' func (p *Parser) parseSetMeta() (*Command, error) { p.nextToken() // consume METADATA // Expect OF if p.curToken.Type != TokenOf { return nil, fmt.Errorf("expected OF after SET METADATA") } p.nextToken() // Expect DOCUMENT if p.curToken.Type != TokenDocument { return nil, fmt.Errorf("expected DOCUMENT after SET METADATA OF") } p.nextToken() // Parse doc_id docID, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected doc_id: %w", err) } cmd := NewCommand("set_meta") cmd.Params["doc_id"] = docID p.nextToken() // Expect TO if p.curToken.Type != TokenTo { return nil, fmt.Errorf("expected TO after doc_id") } p.nextToken() // Parse meta JSON meta, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected meta JSON: %w", err) } cmd.Params["meta"] = meta p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseRemoveTags parses: REMOVE TAGS 'tag1', 'tag2' from DATASET 'dataset_name'; func (p *Parser) parseRemoveTags() (*Command, error) { p.nextToken() // consume TAGS // Parse first tag tag, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected tag: %w", err) } tags := []string{tag} // Parse additional tags separated by commas for { p.nextToken() if p.curToken.Type == TokenComma { p.nextToken() tag, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected tag after comma: %w", err) } tags = append(tags, tag) } else { break } } cmd := NewCommand("rm_tags") cmd.Params["tags"] = tags // Expect from if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM after tags") } p.nextToken() // Expect DATASET if p.curToken.Type != TokenDataset { return nil, fmt.Errorf("expected DATASET after FROM") } p.nextToken() // Parse dataset_name datasetName, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected dataset_name: %w", err) } cmd.Params["dataset_name"] = datasetName // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil } // parseRemoveChunk parses: // - REMOVE CHUNKS 'chunk_id1', 'chunk_id2' FROM DOCUMENT 'doc_id'; // - REMOVE ALL CHUNKS FROM DOCUMENT 'doc_id'; func (p *Parser) parseRemoveChunk() (*Command, error) { cmd := NewCommand("remove_chunks") // Check if ALL CHUNKS - if we came here from TokenAll case, curToken is already ALL if p.curToken.Type == TokenAll { p.nextToken() // consume ALL if p.curToken.Type != TokenChunks { return nil, fmt.Errorf("expected CHUNKS after ALL") } p.nextToken() // consume CHUNKS cmd.Params["delete_all"] = true } else { // curToken is TokenChunks, consume it first p.nextToken() // Multiple chunks: REMOVE CHUNKS 'id1', 'id2' FROM DOCUMENT 'doc_id' // Parse first chunk ID chunkID, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected chunk_id: %w", err) } chunkIDs := []string{chunkID} // Parse additional chunk IDs separated by commas for { p.nextToken() if p.curToken.Type == TokenComma { p.nextToken() chunkID, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected chunk_id after comma: %w", err) } chunkIDs = append(chunkIDs, chunkID) } else { break } } cmd.Params["chunk_ids"] = chunkIDs } // Expect FROM if p.curToken.Type != TokenFrom { return nil, fmt.Errorf("expected FROM after chunk(s)") } p.nextToken() // Expect DOCUMENT if p.curToken.Type != TokenDocument { return nil, fmt.Errorf("expected DOCUMENT after FROM") } p.nextToken() // Parse doc_id docID, err := p.parseQuotedString() if err != nil { return nil, fmt.Errorf("expected doc_id: %w", err) } cmd.Params["doc_id"] = docID p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() } return cmd, nil }